From f3a9dd11e2a9978af278817be48682e8b8848d9c Mon Sep 17 00:00:00 2001 From: Edmar Moretti Date: Tue, 11 Jun 2013 22:35:00 +0000 Subject: [PATCH] Atualização da biblioteca ccc2 --- pacotes/ccc2/ccc2sage.js | 122 -------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/ccc2sage.php | 22 ---------------------- pacotes/ccc2/cdf/jquery.js | 154 ---------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/compactajs.php | 221 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/compacto/Area.js | 1 - pacotes/ccc2/compacto/Atom.js | 1 - pacotes/ccc2/compacto/Axis.js | 1 - pacotes/ccc2/compacto/Bar.js | 1 - pacotes/ccc2/compacto/BarPlot.js | 1 - pacotes/ccc2/compacto/BarPlotAbstract.js | 1 - pacotes/ccc2/compacto/BasicSign.js | 1 - pacotes/ccc2/compacto/BoxPlot.js | 1 - pacotes/ccc2/compacto/BoxplotChartTranslationOper.js | 1 - pacotes/ccc2/compacto/BulletGroupScene.js | 1 - pacotes/ccc2/compacto/BulletItemDefaultRenderer.js | 1 - pacotes/ccc2/compacto/BulletItemRenderer.js | 1 - pacotes/ccc2/compacto/BulletItemScene.js | 1 - pacotes/ccc2/compacto/BulletItemSceneSelection.js | 1 - pacotes/ccc2/compacto/BulletItemSceneVisibility.js | 1 - pacotes/ccc2/compacto/BulletPlot.js | 1 - pacotes/ccc2/compacto/BulletRootScene.js | 1 - pacotes/ccc2/compacto/CartesianAxis.js | 1 - pacotes/ccc2/compacto/CartesianAxisRootScene.js | 1 - pacotes/ccc2/compacto/CartesianAxisTickScene.js | 1 - pacotes/ccc2/compacto/CartesianFocusWindow.js | 1 - pacotes/ccc2/compacto/CartesianPlot.js | 1 - pacotes/ccc2/compacto/CategoricalPlot.js | 1 - pacotes/ccc2/compacto/ColorAxis.js | 1 - pacotes/ccc2/compacto/Complex.js | 1 - pacotes/ccc2/compacto/ComplexType.js | 1 - pacotes/ccc2/compacto/ComplexTypeProject.js | 1 - pacotes/ccc2/compacto/ComplexView.js | 1 - pacotes/ccc2/compacto/Context.js | 1 - pacotes/ccc2/compacto/CrosstabTranslationOper.js | 1 - pacotes/ccc2/compacto/Data.compat.js | 1 - pacotes/ccc2/compacto/Data.js | 1 - pacotes/ccc2/compacto/Data.operations.js | 1 - pacotes/ccc2/compacto/Data.selected.js | 1 - pacotes/ccc2/compacto/DataOper.js | 1 - pacotes/ccc2/compacto/Datum.js | 1 - pacotes/ccc2/compacto/Dimension.js | 1 - pacotes/ccc2/compacto/DimensionType.js | 1 - pacotes/ccc2/compacto/Dot.js | 1 - pacotes/ccc2/compacto/GroupingOper.js | 1 - pacotes/ccc2/compacto/GroupingSpec.js | 1 - pacotes/ccc2/compacto/HeatGridPlot.js | 1 - pacotes/ccc2/compacto/Label.js | 1 - pacotes/ccc2/compacto/Legend.js | 1 - pacotes/ccc2/compacto/Line.js | 1 - pacotes/ccc2/compacto/LinearInterpolationOper.js | 1 - pacotes/ccc2/compacto/LinearInterpolationOperSeriesState.js | 1 - pacotes/ccc2/compacto/MatrixTranslationOper.js | 1 - pacotes/ccc2/compacto/MetricPointChartTranslationOper.js | 1 - pacotes/ccc2/compacto/MetricPointPlot.js | 1 - pacotes/ccc2/compacto/MetricXYPlot.js | 1 - pacotes/ccc2/compacto/NormalizedBarPlot.js | 1 - pacotes/ccc2/compacto/OptionsBase.js | 1 - pacotes/ccc2/compacto/Panel.js | 1 - pacotes/ccc2/compacto/PiePlot.js | 1 - pacotes/ccc2/compacto/PieSlice.js | 1 - pacotes/ccc2/compacto/Plot.js | 1 - pacotes/ccc2/compacto/PointPlot.js | 1 - pacotes/ccc2/compacto/RelationalTranslationOper.js | 1 - pacotes/ccc2/compacto/Role.js | 1 - pacotes/ccc2/compacto/Rule.js | 1 - pacotes/ccc2/compacto/Scene.js | 1 - pacotes/ccc2/compacto/Sign.js | 1 - pacotes/ccc2/compacto/SizeAxis.js | 1 - pacotes/ccc2/compacto/TranslationOper.js | 1 - pacotes/ccc2/compacto/Var.js | 1 - pacotes/ccc2/compacto/WaterfallBulletGroupScene.js | 1 - pacotes/ccc2/compacto/WaterfallPlot.js | 1 - pacotes/ccc2/compacto/ZeroInterpolationOper.js | 1 - pacotes/ccc2/compacto/ZeroInterpolationOperSeriesState.js | 1 - pacotes/ccc2/compacto/_data.js | 1 - pacotes/ccc2/compacto/def.js | 1 - pacotes/ccc2/compacto/protovis-d3.3.js | 1 - pacotes/ccc2/compacto/protovis-msie.js | 1 - pacotes/ccc2/compacto/pvc.color.js | 1 - pacotes/ccc2/compacto/pvc.js | 1 - pacotes/ccc2/compacto/pvc.options.js | 1 - pacotes/ccc2/compacto/pvc.text.js | 1 - pacotes/ccc2/compacto/pvc.trends.js | 1 - pacotes/ccc2/compacto/pvcAbstract.js | 1 - pacotes/ccc2/compacto/pvcAxisPanel.js | 1 - pacotes/ccc2/compacto/pvcAxisTitlePanel.js | 1 - pacotes/ccc2/compacto/pvcBarAbstract.js | 1 - pacotes/ccc2/compacto/pvcBarAbstractPanel.js | 1 - pacotes/ccc2/compacto/pvcBarChart.js | 1 - pacotes/ccc2/compacto/pvcBarPanel.js | 1 - pacotes/ccc2/compacto/pvcBaseChart.axes.js | 1 - pacotes/ccc2/compacto/pvcBaseChart.data.js | 1 - pacotes/ccc2/compacto/pvcBaseChart.extension.js | 1 - pacotes/ccc2/compacto/pvcBaseChart.js | 1 - pacotes/ccc2/compacto/pvcBaseChart.panels.js | 1 - pacotes/ccc2/compacto/pvcBaseChart.plots.js | 1 - pacotes/ccc2/compacto/pvcBaseChart.selection.js | 1 - pacotes/ccc2/compacto/pvcBaseChart.visualRoles.js | 1 - pacotes/ccc2/compacto/pvcBasePanel.js | 1 - pacotes/ccc2/compacto/pvcBoxplotChart.js | 1 - pacotes/ccc2/compacto/pvcBoxplotPanel.js | 1 - pacotes/ccc2/compacto/pvcBulletChart.js | 1 - pacotes/ccc2/compacto/pvcCartesianAbstract.js | 1 - pacotes/ccc2/compacto/pvcCartesianAbstractPanel.js | 1 - pacotes/ccc2/compacto/pvcCartesianGridDockingPanel.js | 1 - pacotes/ccc2/compacto/pvcCategoricalAbstract.js | 1 - pacotes/ccc2/compacto/pvcCategoricalAbstractPanel.js | 1 - pacotes/ccc2/compacto/pvcDataTree.js | 1 - pacotes/ccc2/compacto/pvcGridDockingPanel.js | 1 - pacotes/ccc2/compacto/pvcHeatGridChart.js | 1 - pacotes/ccc2/compacto/pvcHeatGridPanel.js | 1 - pacotes/ccc2/compacto/pvcLegendPanel.js | 1 - pacotes/ccc2/compacto/pvcMetricPoint.js | 1 - pacotes/ccc2/compacto/pvcMetricPointPanel.js | 1 - pacotes/ccc2/compacto/pvcMetricXYAbstract.js | 1 - pacotes/ccc2/compacto/pvcMultiChartPanel.js | 1 - pacotes/ccc2/compacto/pvcNormalizedBarChart.js | 1 - pacotes/ccc2/compacto/pvcNormalizedBarPanel.js | 1 - pacotes/ccc2/compacto/pvcParallelCoordinates.js | 1 - pacotes/ccc2/compacto/pvcPieChart.js | 1 - pacotes/ccc2/compacto/pvcPiePanel.js | 1 - pacotes/ccc2/compacto/pvcPlotBgPanel.js | 1 - pacotes/ccc2/compacto/pvcPlotPanel.js | 1 - pacotes/ccc2/compacto/pvcPoint.js | 1 - pacotes/ccc2/compacto/pvcPointPanel.js | 1 - pacotes/ccc2/compacto/pvcTitlePanel.js | 1 - pacotes/ccc2/compacto/pvcTitlePanelAbstract.js | 1 - pacotes/ccc2/compacto/pvcWaterfallChart.js | 1 - pacotes/ccc2/compacto/pvcWaterfallPanel.js | 1 - pacotes/ccc2/compacto/tipsy.js | 1 - pacotes/ccc2/def/def.js | 2704 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/lib/jquery.tipsy.js | 319 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/lib/protovis-d3.3.js | 21790 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/lib/protovis-msie.js | 1416 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/lib/tipsy.css | 33 --------------------------------- pacotes/ccc2/lib/tipsy.js | 709 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/licenca.txt | 341 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc-r2.0.js | 728 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/_namespace.pvc.js | 5 ----- pacotes/ccc2/pvc/data/Atom.js | 100 ---------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/Complex.js | 231 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/ComplexView.js | 42 ------------------------------------------ pacotes/ccc2/pvc/data/Data.compat.js | 159 --------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/Data.js | 576 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/data/Data.operations.js | 1055 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/Data.selected.js | 299 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/DataOper.js | 32 -------------------------------- pacotes/ccc2/pvc/data/Datum.js | 140 -------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/Dimension.js | 1293 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/GroupingOper.js | 482 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/GroupingSpec.js | 467 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/LinearInterpolationOper.js | 167 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/LinearInterpolationOperSeriesState.js | 176 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/ZeroInterpolationOper.js | 99 --------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/ZeroInterpolationOperSeriesState.js | 124 ---------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/_data.js | 101 ----------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/meta/ComplexType.js | 442 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/meta/ComplexTypeProject.js | 144 ------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/data/meta/DimensionType.js | 576 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/data/translation/BoxplotChartTranslationOper.js | 44 -------------------------------------------- pacotes/ccc2/pvc/data/translation/CrosstabTranslationOper.js | 741 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/translation/MatrixTranslationOper.js | 254 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/translation/MetricPointChartTranslationOper.js | 94 ---------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/translation/RelationalTranslationOper.js | 352 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/data/translation/TranslationOper.js | 477 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvc.color.js | 518 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvc.js | 1568 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvc.options.js | 433 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvc.text.js | 120 ------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/pvc.trends.js | 208 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcAbstract.js | 52 ---------------------------------------------------- pacotes/ccc2/pvc/pvcAxisPanel.js | 1664 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcAxisTitlePanel.js | 35 ----------------------------------- pacotes/ccc2/pvc/pvcBarAbstract.js | 65 ----------------------------------------------------------------- pacotes/ccc2/pvc/pvcBarAbstractPanel.js | 376 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBarChart.js | 107 ----------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBarPanel.js | 7 ------- pacotes/ccc2/pvc/pvcBaseChart.axes.js | 337 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBaseChart.data.js | 589 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBaseChart.extension.js | 154 ---------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBaseChart.js | 785 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBaseChart.panels.js | 276 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/pvcBaseChart.plots.js | 92 -------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBaseChart.selection.js | 172 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBaseChart.visualRoles.js | 534 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/pvcBasePanel.js | 2263 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBoxplotChart.js | 130 ---------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBoxplotPanel.js | 332 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcBulletChart.js | 517 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcCartesianAbstract.js | 725 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcCartesianAbstractPanel.js | 142 ---------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcCartesianGridDockingPanel.js | 723 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcCategoricalAbstract.js | 446 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcCategoricalAbstractPanel.js | 9 --------- pacotes/ccc2/pvc/pvcDataTree.js | 718 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcGridDockingPanel.js | 535 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcHeatGridChart.js | 159 --------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcHeatGridPanel.js | 519 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcLegendPanel.js | 229 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcMetricPoint.js | 201 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcMetricPointPanel.js | 731 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcMetricXYAbstract.js | 147 --------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcMultiChartPanel.js | 538 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcNormalizedBarChart.js | 55 ------------------------------------------------------- pacotes/ccc2/pvc/pvcNormalizedBarPanel.js | 11 ----------- pacotes/ccc2/pvc/pvcParallelCoordinates.js | 600 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/pvcPieChart.js | 63 --------------------------------------------------------------- pacotes/ccc2/pvc/pvcPiePanel.js | 768 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/pvcPlotBgPanel.js | 30 ------------------------------ pacotes/ccc2/pvc/pvcPlotPanel.js | 52 ---------------------------------------------------- pacotes/ccc2/pvc/pvcPoint.js | 232 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcPointPanel.js | 853 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcTitlePanel.js | 28 ---------------------------- pacotes/ccc2/pvc/pvcTitlePanelAbstract.js | 210 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/pvcWaterfallChart.js | 182 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/pvcWaterfallPanel.js | 339 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/Axis.js | 219 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/CartesianAxis.js | 689 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/CartesianAxisRootScene.js | 15 --------------- pacotes/ccc2/pvc/visual/CartesianAxisTickScene.js | 24 ------------------------ pacotes/ccc2/pvc/visual/CartesianFocusWindow.js | 627 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/ColorAxis.js | 551 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/Context.js | 129 --------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/Legend.js | 121 ------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/OptionsBase.js | 168 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/visual/Role.js | 370 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/Scene.js | 358 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/SizeAxis.js | 81 --------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/Var.js | 147 --------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/legend/BulletGroupScene.js | 90 ------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/visual/legend/BulletItemDefaultRenderer.js | 124 ---------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/legend/BulletItemRenderer.js | 29 ----------------------------- pacotes/ccc2/pvc/visual/legend/BulletItemScene.js | 106 ---------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/legend/BulletItemSceneSelection.js | 52 ---------------------------------------------------- pacotes/ccc2/pvc/visual/legend/BulletItemSceneVisibility.js | 41 ----------------------------------------- pacotes/ccc2/pvc/visual/legend/BulletRootScene.js | 191 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/legend/WaterfallBulletGroupScene.js | 62 -------------------------------------------------------------- pacotes/ccc2/pvc/visual/plot/BarPlot.js | 13 ------------- pacotes/ccc2/pvc/visual/plot/BarPlotAbstract.js | 86 -------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/plot/BoxPlot.js | 73 ------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/plot/BulletPlot.js | 27 --------------------------- pacotes/ccc2/pvc/visual/plot/CartesianPlot.js | 136 ---------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/plot/CategoricalPlot.js | 35 ----------------------------------- pacotes/ccc2/pvc/visual/plot/HeatGridPlot.js | 72 ------------------------------------------------------------------------ pacotes/ccc2/pvc/visual/plot/MetricPointPlot.js | 64 ---------------------------------------------------------------- pacotes/ccc2/pvc/visual/plot/MetricXYPlot.js | 32 -------------------------------- pacotes/ccc2/pvc/visual/plot/NormalizedBarPlot.js | 27 --------------------------- pacotes/ccc2/pvc/visual/plot/PiePlot.js | 170 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/plot/Plot.js | 150 ------------------------------------------------------------------------------------------------------------------------------------------------------ pacotes/ccc2/pvc/visual/plot/PointPlot.js | 58 ---------------------------------------------------------- pacotes/ccc2/pvc/visual/plot/WaterfallPlot.js | 63 --------------------------------------------------------------- pacotes/ccc2/pvc/visual/sign/Area.js | 81 --------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/sign/Bar.js | 92 -------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/sign/BasicSign.js | 161 ----------------------------------------------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/sign/Dot.js | 118 ---------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/sign/Label.js | 24 ------------------------ pacotes/ccc2/pvc/visual/sign/Line.js | 93 --------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/sign/Panel.js | 25 ------------------------- pacotes/ccc2/pvc/visual/sign/PieSlice.js | 123 --------------------------------------------------------------------------------------------------------------------------- pacotes/ccc2/pvc/visual/sign/Rule.js | 60 ------------------------------------------------------------ pacotes/ccc2/pvc/visual/sign/Sign.js | 381 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 261 files changed, 0 insertions(+), 64294 deletions(-) delete mode 100755 pacotes/ccc2/ccc2sage.js delete mode 100755 pacotes/ccc2/ccc2sage.php delete mode 100755 pacotes/ccc2/cdf/jquery.js delete mode 100755 pacotes/ccc2/compactajs.php delete mode 100755 pacotes/ccc2/compacto/Area.js delete mode 100755 pacotes/ccc2/compacto/Atom.js delete mode 100755 pacotes/ccc2/compacto/Axis.js delete mode 100755 pacotes/ccc2/compacto/Bar.js delete mode 100755 pacotes/ccc2/compacto/BarPlot.js delete mode 100755 pacotes/ccc2/compacto/BarPlotAbstract.js delete mode 100755 pacotes/ccc2/compacto/BasicSign.js delete mode 100755 pacotes/ccc2/compacto/BoxPlot.js delete mode 100755 pacotes/ccc2/compacto/BoxplotChartTranslationOper.js delete mode 100755 pacotes/ccc2/compacto/BulletGroupScene.js delete mode 100755 pacotes/ccc2/compacto/BulletItemDefaultRenderer.js delete mode 100755 pacotes/ccc2/compacto/BulletItemRenderer.js delete mode 100755 pacotes/ccc2/compacto/BulletItemScene.js delete mode 100755 pacotes/ccc2/compacto/BulletItemSceneSelection.js delete mode 100755 pacotes/ccc2/compacto/BulletItemSceneVisibility.js delete mode 100755 pacotes/ccc2/compacto/BulletPlot.js delete mode 100755 pacotes/ccc2/compacto/BulletRootScene.js delete mode 100755 pacotes/ccc2/compacto/CartesianAxis.js delete mode 100755 pacotes/ccc2/compacto/CartesianAxisRootScene.js delete mode 100755 pacotes/ccc2/compacto/CartesianAxisTickScene.js delete mode 100755 pacotes/ccc2/compacto/CartesianFocusWindow.js delete mode 100755 pacotes/ccc2/compacto/CartesianPlot.js delete mode 100755 pacotes/ccc2/compacto/CategoricalPlot.js delete mode 100755 pacotes/ccc2/compacto/ColorAxis.js delete mode 100755 pacotes/ccc2/compacto/Complex.js delete mode 100755 pacotes/ccc2/compacto/ComplexType.js delete mode 100755 pacotes/ccc2/compacto/ComplexTypeProject.js delete mode 100755 pacotes/ccc2/compacto/ComplexView.js delete mode 100755 pacotes/ccc2/compacto/Context.js delete mode 100755 pacotes/ccc2/compacto/CrosstabTranslationOper.js delete mode 100755 pacotes/ccc2/compacto/Data.compat.js delete mode 100755 pacotes/ccc2/compacto/Data.js delete mode 100755 pacotes/ccc2/compacto/Data.operations.js delete mode 100755 pacotes/ccc2/compacto/Data.selected.js delete mode 100755 pacotes/ccc2/compacto/DataOper.js delete mode 100755 pacotes/ccc2/compacto/Datum.js delete mode 100755 pacotes/ccc2/compacto/Dimension.js delete mode 100755 pacotes/ccc2/compacto/DimensionType.js delete mode 100755 pacotes/ccc2/compacto/Dot.js delete mode 100755 pacotes/ccc2/compacto/GroupingOper.js delete mode 100755 pacotes/ccc2/compacto/GroupingSpec.js delete mode 100755 pacotes/ccc2/compacto/HeatGridPlot.js delete mode 100755 pacotes/ccc2/compacto/Label.js delete mode 100755 pacotes/ccc2/compacto/Legend.js delete mode 100755 pacotes/ccc2/compacto/Line.js delete mode 100755 pacotes/ccc2/compacto/LinearInterpolationOper.js delete mode 100755 pacotes/ccc2/compacto/LinearInterpolationOperSeriesState.js delete mode 100755 pacotes/ccc2/compacto/MatrixTranslationOper.js delete mode 100755 pacotes/ccc2/compacto/MetricPointChartTranslationOper.js delete mode 100755 pacotes/ccc2/compacto/MetricPointPlot.js delete mode 100755 pacotes/ccc2/compacto/MetricXYPlot.js delete mode 100755 pacotes/ccc2/compacto/NormalizedBarPlot.js delete mode 100755 pacotes/ccc2/compacto/OptionsBase.js delete mode 100755 pacotes/ccc2/compacto/Panel.js delete mode 100755 pacotes/ccc2/compacto/PiePlot.js delete mode 100755 pacotes/ccc2/compacto/PieSlice.js delete mode 100755 pacotes/ccc2/compacto/Plot.js delete mode 100755 pacotes/ccc2/compacto/PointPlot.js delete mode 100755 pacotes/ccc2/compacto/RelationalTranslationOper.js delete mode 100755 pacotes/ccc2/compacto/Role.js delete mode 100755 pacotes/ccc2/compacto/Rule.js delete mode 100755 pacotes/ccc2/compacto/Scene.js delete mode 100755 pacotes/ccc2/compacto/Sign.js delete mode 100755 pacotes/ccc2/compacto/SizeAxis.js delete mode 100755 pacotes/ccc2/compacto/TranslationOper.js delete mode 100755 pacotes/ccc2/compacto/Var.js delete mode 100755 pacotes/ccc2/compacto/WaterfallBulletGroupScene.js delete mode 100755 pacotes/ccc2/compacto/WaterfallPlot.js delete mode 100755 pacotes/ccc2/compacto/ZeroInterpolationOper.js delete mode 100755 pacotes/ccc2/compacto/ZeroInterpolationOperSeriesState.js delete mode 100755 pacotes/ccc2/compacto/_data.js delete mode 100755 pacotes/ccc2/compacto/def.js delete mode 100755 pacotes/ccc2/compacto/protovis-d3.3.js delete mode 100755 pacotes/ccc2/compacto/protovis-msie.js delete mode 100755 pacotes/ccc2/compacto/pvc.color.js delete mode 100755 pacotes/ccc2/compacto/pvc.js delete mode 100755 pacotes/ccc2/compacto/pvc.options.js delete mode 100755 pacotes/ccc2/compacto/pvc.text.js delete mode 100755 pacotes/ccc2/compacto/pvc.trends.js delete mode 100755 pacotes/ccc2/compacto/pvcAbstract.js delete mode 100755 pacotes/ccc2/compacto/pvcAxisPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcAxisTitlePanel.js delete mode 100755 pacotes/ccc2/compacto/pvcBarAbstract.js delete mode 100755 pacotes/ccc2/compacto/pvcBarAbstractPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcBarChart.js delete mode 100755 pacotes/ccc2/compacto/pvcBarPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcBaseChart.axes.js delete mode 100755 pacotes/ccc2/compacto/pvcBaseChart.data.js delete mode 100755 pacotes/ccc2/compacto/pvcBaseChart.extension.js delete mode 100755 pacotes/ccc2/compacto/pvcBaseChart.js delete mode 100755 pacotes/ccc2/compacto/pvcBaseChart.panels.js delete mode 100755 pacotes/ccc2/compacto/pvcBaseChart.plots.js delete mode 100755 pacotes/ccc2/compacto/pvcBaseChart.selection.js delete mode 100755 pacotes/ccc2/compacto/pvcBaseChart.visualRoles.js delete mode 100755 pacotes/ccc2/compacto/pvcBasePanel.js delete mode 100755 pacotes/ccc2/compacto/pvcBoxplotChart.js delete mode 100755 pacotes/ccc2/compacto/pvcBoxplotPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcBulletChart.js delete mode 100755 pacotes/ccc2/compacto/pvcCartesianAbstract.js delete mode 100755 pacotes/ccc2/compacto/pvcCartesianAbstractPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcCartesianGridDockingPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcCategoricalAbstract.js delete mode 100755 pacotes/ccc2/compacto/pvcCategoricalAbstractPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcDataTree.js delete mode 100755 pacotes/ccc2/compacto/pvcGridDockingPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcHeatGridChart.js delete mode 100755 pacotes/ccc2/compacto/pvcHeatGridPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcLegendPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcMetricPoint.js delete mode 100755 pacotes/ccc2/compacto/pvcMetricPointPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcMetricXYAbstract.js delete mode 100755 pacotes/ccc2/compacto/pvcMultiChartPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcNormalizedBarChart.js delete mode 100755 pacotes/ccc2/compacto/pvcNormalizedBarPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcParallelCoordinates.js delete mode 100755 pacotes/ccc2/compacto/pvcPieChart.js delete mode 100755 pacotes/ccc2/compacto/pvcPiePanel.js delete mode 100755 pacotes/ccc2/compacto/pvcPlotBgPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcPlotPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcPoint.js delete mode 100755 pacotes/ccc2/compacto/pvcPointPanel.js delete mode 100755 pacotes/ccc2/compacto/pvcTitlePanel.js delete mode 100755 pacotes/ccc2/compacto/pvcTitlePanelAbstract.js delete mode 100755 pacotes/ccc2/compacto/pvcWaterfallChart.js delete mode 100755 pacotes/ccc2/compacto/pvcWaterfallPanel.js delete mode 100755 pacotes/ccc2/compacto/tipsy.js delete mode 100755 pacotes/ccc2/def/def.js delete mode 100755 pacotes/ccc2/lib/jquery.tipsy.js delete mode 100755 pacotes/ccc2/lib/protovis-d3.3.js delete mode 100755 pacotes/ccc2/lib/protovis-msie.js delete mode 100755 pacotes/ccc2/lib/tipsy.css delete mode 100755 pacotes/ccc2/lib/tipsy.js delete mode 100755 pacotes/ccc2/licenca.txt delete mode 100644 pacotes/ccc2/pvc-r2.0.js delete mode 100755 pacotes/ccc2/pvc/_namespace.pvc.js delete mode 100755 pacotes/ccc2/pvc/data/Atom.js delete mode 100755 pacotes/ccc2/pvc/data/Complex.js delete mode 100755 pacotes/ccc2/pvc/data/ComplexView.js delete mode 100755 pacotes/ccc2/pvc/data/Data.compat.js delete mode 100755 pacotes/ccc2/pvc/data/Data.js delete mode 100755 pacotes/ccc2/pvc/data/Data.operations.js delete mode 100755 pacotes/ccc2/pvc/data/Data.selected.js delete mode 100755 pacotes/ccc2/pvc/data/DataOper.js delete mode 100755 pacotes/ccc2/pvc/data/Datum.js delete mode 100755 pacotes/ccc2/pvc/data/Dimension.js delete mode 100755 pacotes/ccc2/pvc/data/GroupingOper.js delete mode 100755 pacotes/ccc2/pvc/data/GroupingSpec.js delete mode 100755 pacotes/ccc2/pvc/data/LinearInterpolationOper.js delete mode 100755 pacotes/ccc2/pvc/data/LinearInterpolationOperSeriesState.js delete mode 100755 pacotes/ccc2/pvc/data/ZeroInterpolationOper.js delete mode 100755 pacotes/ccc2/pvc/data/ZeroInterpolationOperSeriesState.js delete mode 100755 pacotes/ccc2/pvc/data/_data.js delete mode 100755 pacotes/ccc2/pvc/data/meta/ComplexType.js delete mode 100755 pacotes/ccc2/pvc/data/meta/ComplexTypeProject.js delete mode 100755 pacotes/ccc2/pvc/data/meta/DimensionType.js delete mode 100755 pacotes/ccc2/pvc/data/translation/BoxplotChartTranslationOper.js delete mode 100755 pacotes/ccc2/pvc/data/translation/CrosstabTranslationOper.js delete mode 100755 pacotes/ccc2/pvc/data/translation/MatrixTranslationOper.js delete mode 100755 pacotes/ccc2/pvc/data/translation/MetricPointChartTranslationOper.js delete mode 100755 pacotes/ccc2/pvc/data/translation/RelationalTranslationOper.js delete mode 100755 pacotes/ccc2/pvc/data/translation/TranslationOper.js delete mode 100755 pacotes/ccc2/pvc/pvc.color.js delete mode 100755 pacotes/ccc2/pvc/pvc.js delete mode 100755 pacotes/ccc2/pvc/pvc.options.js delete mode 100755 pacotes/ccc2/pvc/pvc.text.js delete mode 100755 pacotes/ccc2/pvc/pvc.trends.js delete mode 100755 pacotes/ccc2/pvc/pvcAbstract.js delete mode 100755 pacotes/ccc2/pvc/pvcAxisPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcAxisTitlePanel.js delete mode 100755 pacotes/ccc2/pvc/pvcBarAbstract.js delete mode 100755 pacotes/ccc2/pvc/pvcBarAbstractPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcBarChart.js delete mode 100755 pacotes/ccc2/pvc/pvcBarPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcBaseChart.axes.js delete mode 100755 pacotes/ccc2/pvc/pvcBaseChart.data.js delete mode 100755 pacotes/ccc2/pvc/pvcBaseChart.extension.js delete mode 100755 pacotes/ccc2/pvc/pvcBaseChart.js delete mode 100755 pacotes/ccc2/pvc/pvcBaseChart.panels.js delete mode 100755 pacotes/ccc2/pvc/pvcBaseChart.plots.js delete mode 100755 pacotes/ccc2/pvc/pvcBaseChart.selection.js delete mode 100755 pacotes/ccc2/pvc/pvcBaseChart.visualRoles.js delete mode 100755 pacotes/ccc2/pvc/pvcBasePanel.js delete mode 100755 pacotes/ccc2/pvc/pvcBoxplotChart.js delete mode 100755 pacotes/ccc2/pvc/pvcBoxplotPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcBulletChart.js delete mode 100755 pacotes/ccc2/pvc/pvcCartesianAbstract.js delete mode 100755 pacotes/ccc2/pvc/pvcCartesianAbstractPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcCartesianGridDockingPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcCategoricalAbstract.js delete mode 100755 pacotes/ccc2/pvc/pvcCategoricalAbstractPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcDataTree.js delete mode 100755 pacotes/ccc2/pvc/pvcGridDockingPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcHeatGridChart.js delete mode 100755 pacotes/ccc2/pvc/pvcHeatGridPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcLegendPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcMetricPoint.js delete mode 100755 pacotes/ccc2/pvc/pvcMetricPointPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcMetricXYAbstract.js delete mode 100755 pacotes/ccc2/pvc/pvcMultiChartPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcNormalizedBarChart.js delete mode 100755 pacotes/ccc2/pvc/pvcNormalizedBarPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcParallelCoordinates.js delete mode 100755 pacotes/ccc2/pvc/pvcPieChart.js delete mode 100755 pacotes/ccc2/pvc/pvcPiePanel.js delete mode 100755 pacotes/ccc2/pvc/pvcPlotBgPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcPlotPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcPoint.js delete mode 100755 pacotes/ccc2/pvc/pvcPointPanel.js delete mode 100755 pacotes/ccc2/pvc/pvcTitlePanel.js delete mode 100755 pacotes/ccc2/pvc/pvcTitlePanelAbstract.js delete mode 100755 pacotes/ccc2/pvc/pvcWaterfallChart.js delete mode 100755 pacotes/ccc2/pvc/pvcWaterfallPanel.js delete mode 100755 pacotes/ccc2/pvc/visual/Axis.js delete mode 100755 pacotes/ccc2/pvc/visual/CartesianAxis.js delete mode 100755 pacotes/ccc2/pvc/visual/CartesianAxisRootScene.js delete mode 100755 pacotes/ccc2/pvc/visual/CartesianAxisTickScene.js delete mode 100755 pacotes/ccc2/pvc/visual/CartesianFocusWindow.js delete mode 100755 pacotes/ccc2/pvc/visual/ColorAxis.js delete mode 100755 pacotes/ccc2/pvc/visual/Context.js delete mode 100755 pacotes/ccc2/pvc/visual/Legend.js delete mode 100755 pacotes/ccc2/pvc/visual/OptionsBase.js delete mode 100755 pacotes/ccc2/pvc/visual/Role.js delete mode 100755 pacotes/ccc2/pvc/visual/Scene.js delete mode 100755 pacotes/ccc2/pvc/visual/SizeAxis.js delete mode 100755 pacotes/ccc2/pvc/visual/Var.js delete mode 100755 pacotes/ccc2/pvc/visual/legend/BulletGroupScene.js delete mode 100755 pacotes/ccc2/pvc/visual/legend/BulletItemDefaultRenderer.js delete mode 100755 pacotes/ccc2/pvc/visual/legend/BulletItemRenderer.js delete mode 100755 pacotes/ccc2/pvc/visual/legend/BulletItemScene.js delete mode 100755 pacotes/ccc2/pvc/visual/legend/BulletItemSceneSelection.js delete mode 100755 pacotes/ccc2/pvc/visual/legend/BulletItemSceneVisibility.js delete mode 100755 pacotes/ccc2/pvc/visual/legend/BulletRootScene.js delete mode 100755 pacotes/ccc2/pvc/visual/legend/WaterfallBulletGroupScene.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/BarPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/BarPlotAbstract.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/BoxPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/BulletPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/CartesianPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/CategoricalPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/HeatGridPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/MetricPointPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/MetricXYPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/NormalizedBarPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/PiePlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/Plot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/PointPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/plot/WaterfallPlot.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/Area.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/Bar.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/BasicSign.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/Dot.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/Label.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/Line.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/Panel.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/PieSlice.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/Rule.js delete mode 100755 pacotes/ccc2/pvc/visual/sign/Sign.js diff --git a/pacotes/ccc2/ccc2sage.js b/pacotes/ccc2/ccc2sage.js deleted file mode 100755 index dbb617f..0000000 --- a/pacotes/ccc2/ccc2sage.js +++ /dev/null @@ -1,122 +0,0 @@ -var pvc=def.globalSpace('pvc',{debug:0});(function(){(function(){if((typeof window.location)!=='undefined'){var url=window.location.href;if(url&&(/\bdebug=true\b/).test(url)){var m=/\bdebugLevel=(\d+)/.exec(url);pvc.debug=m?(+m[1]):3}}}());pvc.invisibleFill='rgba(127,127,127,0.00001)';pvc.logSeparator="------------------------------------------";var arraySlice=pvc.arraySlice=Array.prototype.slice;pvc.setDebug=function(level){level=+level;pvc.debug=isNaN(level)?0:level;installPvcLog();syncTipsyLog();return pvc.debug};pvc._installLog=function(o,pto,pfrom,prompt){if(!pfrom){pfrom=pto}var c=console;var m=c[pfrom]||c.log;var fun;if(m){var mask=prompt+": %s";if(!def.fun.is(m)){var apply=Function.prototype.apply;fun=function(){apply.call(m,c,def.array.append([mask],arguments))}}else{fun=m.bind(console,mask)}}o[pto]=fun};function installPvcLog(){if(pvc.debug&&typeof console!=="undefined"){['log','info',['trace','debug'],'error','warn','group','groupEnd'].forEach(function(ps){ps=ps instanceof Array?ps:[ps,ps];pvc._installLog(pvc,ps[0],ps[1],'[pvChart]')})}else{if(pvc.debug>1){pvc.debug=1}['log','info','trace','warn','group','groupEnd'].forEach(function(p){pvc[p]=def.noop});pvc.error=function(e){if(e&&typeof e==='object'&&e.message){e=e.message}throw new Error("[pvChart ERROR]: "+e)}}}installPvcLog();pvc.logError=pvc.error;pv.error=pvc.error;function syncTipsyLog(){var tip=pv.Behavior.tipsy;if(tip&&tip.setDebug){tip.setDebug(pvc.debug);tip.log=pvc.log}}syncTipsyLog();pvc.defaultCompatVersion=function(compatVersion){var defaults=pvc.BaseChart.prototype.defaults;if(compatVersion!=null){return defaults.compatVersion=compatVersion}return defaults.compatVersion};pvc.cloneMatrix=function(m){return m.map(function(d){return d.slice()})};pvc.stringify=function(t,keyArgs){var maxLevel=def.get(keyArgs,'maxLevel')||5;var out=[];pvc.stringifyRecursive(out,t,maxLevel,keyArgs);return out.join('')};pvc.stringifyRecursive=function(out,t,remLevels,keyArgs){if(remLevels>0){remLevels--;switch(typeof t){case'undefined':return out.push('undefined');case'object':if(!t){out.push('null');return true}if(def.fun.is(t.stringify)){return t.stringify(out,remLevels,keyArgs)}if(t instanceof Array){out.push('[');t.forEach(function(item,index){if(index){out.push(', ')}if(!pvc.stringifyRecursive(out,item,remLevels,keyArgs)){out.pop()}});out.push(']')}else{var ownOnly=def.get(keyArgs,'ownOnly',true);if(t===def.global){out.push('');return true}if(def.fun.is(t.cloneNode)){out.push('');return true}if(remLevels>1&&t.constructor!==Object){remLevels=1;ownOnly=true}out.push('{');var first=true;for(var p in t){if(!ownOnly||def.hasOwnProp.call(t,p)){if(!first){out.push(', ')}out.push(p+': ');if(!pvc.stringifyRecursive(out,t[p],remLevels,keyArgs)){out.pop();if(!first){out.pop()}}else if(first){first=false}}}if(first){var s=''+t;if(s!=='[object Object]'){out.push('{'+s+'}')}}out.push('}')}return true;case'number':out.push(''+(Math.round(100000*t)/100000)); return true;case'boolean':out.push(''+t);return true;case'string':out.push(JSON.stringify(t));return true;case'function':if(def.get(keyArgs,'funs',false)){out.push(JSON.stringify(t.toString().substr(0,13)+'...'));return true}return false}out.push("'new ???'");return true}};pvc.orientation={vertical:'vertical',horizontal:'horizontal'};pvc.extensionTag='extension';pvc.extendType=function(type,exts,names){if(exts){var exts2;var addExtension=function(ext,name){if(ext!==undefined){if(!exts2){exts2={}}exts2[name]=def.fun.to(ext)}};if(names){names.forEach(function(name){addExtension(exts[name],name)})}else{def.each(addExtension)}if(exts2){type.add(exts2)}}};pv.Mark.prototype.hasDelegateValue=function(name,tag){var p=this.$propertiesMap[name];if(p){return(!tag||p.tag===tag)}if(this.proto){return this.proto.hasDelegateValue(name,tag)}return false};pvc.defaultColorScheme=null;pvc.brighterColorTransform=function(color){return(color.rgb?color:pv.color(color)).brighter(0.6)};pvc.setDefaultColorScheme=function(colors){return pvc.defaultColorScheme=pvc.colorScheme(colors)};pvc.defaultColor=pv.Colors.category10()('?');pvc.colorScheme=function(colors){if(colors==null){return null}if(typeof colors==='function'){if(!colors.hasOwnProperty('range')){return colors}colors=colors.range()}else{colors=def.array.as(colors)}if(!colors.length){return null}return function(){var scale=pv.colors(colors);scale.domain.apply(scale,arguments);return scale}},pvc.createColorScheme=function(colors){return pvc.colorScheme(colors)||pvc.defaultColorScheme||pv.Colors.category10};pvc.toGrayScale=function(color,alpha,maxGrayLevel,minGrayLevel){color=pv.color(color);var avg=0.299*color.r+0.587*color.g+0.114*color.b;if(maxGrayLevel===undefined){maxGrayLevel=200}else if(maxGrayLevel==null){maxGrayLevel=255}if(minGrayLevel===undefined){minGrayLevel=30}else if(minGrayLevel==null){minGrayLevel=0}var delta=(maxGrayLevel-minGrayLevel);if(delta<=0){avg=maxGrayLevel}else{avg=minGrayLevel+(avg/255)*delta}if(alpha==null){alpha=color.opacity}else if(alpha<0){alpha=(-alpha)*color.opacity}avg=Math.round(avg);return pv.rgb(avg,avg,avg,alpha)};pvc.removeTipsyLegends=function(){try{$('.tipsy').remove()}catch(e){}};pvc.createDateComparer=function(parser,key){if(!key){key=pv.identity}return function(a,b){return parser.parse(key(a))-parser.parse(key(b))}};pvc.time={intervals:{'y':31536e6,'m':2592e6,'d30':2592e6,'w':6048e5,'d7':6048e5,'d':864e5,'h':36e5,'M':6e4,'s':1e3,'ms':1},withoutTime:function(t){return new Date(t.getFullYear(),t.getMonth(),t.getDate())},weekday:{previousOrSelf:function(t,toWd){var wd=t.getDay();var difDays=wd-toWd;if(difDays){var previousOffset=difDays<0?(7+difDays):difDays;t=new Date(t-previousOffset*pvc.time.intervals.d)}return t},nextOrSelf:function(t,toWd){var wd=t.getDay();var difDays=wd-toWd;if(difDays){var nextOffset=difDays>0?(7-difDays):-difDays;t=new Date(t+nextOffset*pvc.time.intervals.d)}return t},closestOrSelf:function(t,toWd){var wd=t.getDay();var difDays=wd-toWd;if(difDays){var D=pvc.time.intervals.d;var sign=difDays>0?1:-1;difDays=Math.abs(difDays);if(difDays>=4){t=new Date(t.getTime()+sign*(7-difDays)*D)}else{t=new Date(t.getTime()-sign*difDays*D)}}return t}}};pv.Format.createParser=function(pvFormat){function parse(value){return pvFormat.parse(value)}return parse};pv.Format.createFormatter=function(pvFormat){function format(value){return value!=null?pvFormat.format(value):""}return format};pvc.buildTitleFromName=function(name){return def.firstUpperCase(name).replace(/([a-z\d])([A-Z])/,"$1 $2")};pvc.buildIndexedId=function(prefix,index){if(index>0){return prefix+""+(index+1)}return prefix};pvc.splitIndexedId=function(indexedId){var match=/^(.*?)(\d*)$/.exec(indexedId);var index=null;if(match[2]){index=Number(match[2]);if(index<=1){index=1}else{index--}}return[match[1],index]};function unwrapExtensionOne(id,prefix){if(id){if(def.object.is(id)){return id.abs}return prefix?(prefix+def.firstUpperCase(id)):id}return prefix}var oneNullArray=[null];pvc.makeExtensionAbsId=function(id,prefix){if(!id){return prefix}return def.query(prefix||oneNullArray).selectMany(function(oneprefix){return def.query(id).select(function(oneid){return unwrapExtensionOne(oneid,oneprefix)})}).where(def.truthy).array()};pvc.parseDistinctIndexArray=function(value,max){value=def.array.as(value);if(value==null){return null}if(max==null){max=Infinity}var a=def.query(value).select(function(index){return+index}).where(function(index){return!isNaN(index)&&index>=0&&index<=max}).distinct().array();return a.length?a:null};pvc.parseLegendClickMode=function(clickMode){if(!clickMode){clickMode='none'}switch(clickMode){case'toggleSelected':case'toggleVisible':case'none':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'legendClickMode' option value: '"+clickMode+"'. Assuming 'none'.")}clickMode='none';break}return clickMode};pvc.parseShape=function(shape){if(shape){switch(shape){case'square':case'circle':case'diamond':case'triangle':case'cross':case'bar':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'shape' option value: '"+shape+"'.")}shape=null;break}}return shape};pvc.parseContinuousColorScaleType=function(scaleType){if(scaleType){switch(scaleType){case'linear':case'normal':case'discrete':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'ScaleType' option value: '"+scaleType+"'.")}scaleType=null;break}}return scaleType};pvc.parseDomainScope=function(scope,orientation){if(scope){switch(scope){case'cell':case'global':break;case'section':if(!orientation){throw def.error.argumentRequired('orientation')}scope=orientation==='y'?'row':'column';break;case'column':case'row':if(orientation&&orientation!==(scope==='row'?'y':'x')){scope='section';if(pvc.debug>=2){pvc.log("[Warning] Invalid 'DomainScope' option value: '"+scope+"' for the orientation: '"+orientation+"'.")}}break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'DomainScope' option value: '"+scope+"'.")}scope=null;break}}return scope};pvc.parseDomainRoundingMode=function(mode){if(mode){switch(mode){case'none':case'nice':case'tick':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'DomainRoundMode' value: '"+mode+"'.")}mode=null;break}}return mode};pvc.parseOverlappedLabelsMode=function(mode){if(mode){switch(mode){case'leave':case'hide':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'OverlappedLabelsMode' option value: '"+mode+"'.")}mode=null;break}}return mode};pvc.castNumber=function(value){if(value!=null){value=+value;if(isNaN(value)){value=null}}return value};pvc.parseWaterDirection=function(value){if(value){switch(value){case'up':case'down':return value}if(pvc.debug>=2){pvc.log("[Warning] Invalid 'WaterDirection' value: '"+value+"'.")}}};pvc.parseTrendType=function(value){if(value){if(value==='none'){return value}if(pvc.trends.has(value)){return value}if(pvc.debug>=2){pvc.log("[Warning] Invalid 'TrendType' value: '"+value+"'.")}}};pvc.parseNullInterpolationMode=function(value){if(value){switch(value){case'none':case'linear':case'zero':return value}if(pvc.debug>=2){pvc.log("[Warning] Invalid 'NullInterpolationMode' value: '"+value+"'.")}}};pvc.parseAlign=function(side,align){var align2,isInvalid;if(side==='left'||side==='right'){align2=align&&pvc.BasePanel.verticalAlign[align];if(!align2){align2='middle';isInvalid=!!align}}else{align2=align&&pvc.BasePanel.horizontalAlign[align];if(!align2){align2='center';isInvalid=!!align}}if(isInvalid&&pvc.debug>=2){pvc.log(def.format("Invalid alignment value '{0}'. Assuming '{1}'.",[align,align2]))}return align2};pvc.parseAnchor=function(anchor){if(anchor){switch(anchor){case'top':case'left':case'center':case'bottom':case'right':return anchor}if(pvc.debug>=2){pvc.log(def.format("Invalid anchor value '{0}'.",[anchor]))}}};pvc.parseAnchorWedge=function(anchor){if(anchor){switch(anchor){case'outer':case'inner':case'center':case'start':case'end':return anchor}if(pvc.debug>=2){pvc.log(def.format("Invalid wedge anchor value '{0}'.",[anchor]))}}};pvc.unionExtents=function(result,range){if(!result){if(!range){return null}result={min:range.min,max:range.max}}else if(range){if(range.minresult.max){result.max=range.max}}return result};pvc.Sides=function(sides){if(sides!=null){this.setSides(sides)}};pvc.Sides.hnames='left right'.split(' ');pvc.Sides.vnames='top bottom'.split(' ');pvc.Sides.names='left right top bottom'.split(' ');pvc.Sides.namesSet=pv.dict(pvc.Sides.names,def.retTrue);pvc.parsePosition=function(side,defaultSide){if(side&&!def.hasOwn(pvc.Sides.namesSet,side)){if(!defaultSide){defaultSide='left'}if(pvc.debug>=2){pvc.log(def.format("Invalid position value '{0}. Assuming '{1}'.",[side,defaultSide]))}side=defaultSide}return side};pvc.Sides.as=function(v){if(v!=null&&!(v instanceof pvc.Sides)){v=new pvc.Sides().setSides(v)}return v};pvc.Sides.prototype.stringify=function(out,remLevels,keyArgs){return pvc.stringifyRecursive(out,def.copyOwn(this),remLevels,keyArgs)};pvc.Sides.prototype.setSides=function(sides){if(typeof sides==='string'){var comps=sides.split(/\s+/).map(function(comp){return pvc.PercentValue.parse(comp)});switch(comps.length){case 1:this.set('all',comps[0]);return this;case 2:this.set('top',comps[0]);this.set('left',comps[1]);this.set('right',comps[1]);this.set('bottom',comps[0]);return this;case 3:this.set('top',comps[0]);this.set('left',comps[1]);this.set('right',comps[1]);this.set('bottom',comps[2]);return this;case 4:this.set('top',comps[0]);this.set('right',comps[1]);this.set('bottom',comps[2]);this.set('left',comps[3]);return this;case 0:return this}}else if(typeof sides==='number'){this.set('all',sides);return this}else if(typeof sides==='object'){if(sides instanceof pvc.PercentValue){this.set('all',sides)}else{this.set('all',sides.all);for(var p in sides){if(p!=='all'&&pvc.Sides.namesSet.hasOwnProperty(p)){this.set(p,sides[p])}}}return this}if(pvc.debug){pvc.log("Invalid 'sides' value: "+pvc.stringify(sides))}return this};pvc.Sides.prototype.set=function(prop,value){value=pvc.PercentValue.parse(value);if(value!=null){if(prop==='all'){pvc.Sides.names.forEach(function(p){this[p]=value},this)}else if(def.hasOwn(pvc.Sides.namesSet,prop)){this[prop]=value}}};pvc.Sides.prototype.resolve=function(width,height){if(typeof width==='object'){height=width.height;width=width.width}var sides={};pvc.Sides.names.forEach(function(side){var value=0;var sideValue=this[side];if(sideValue!=null){if(typeof(sideValue)==='number'){value=sideValue}else{value=sideValue.resolve((side==='left'||side==='right')?width:height)}}sides[side]=value},this);return pvc.Sides.updateSize(sides)};pvc.Sides.updateSize=function(sides){sides.width=(sides.left||0)+(sides.right||0);sides.height=(sides.bottom||0)+(sides.top||0);return sides};pvc.Sides.resolvedMax=function(a,b){var sides={};pvc.Sides.names.forEach(function(side){sides[side]=Math.max(a[side]||0,b[side]||0)});return sides};pvc.Sides.inflate=function(sides,by){var sidesOut={};pvc.Sides.names.forEach(function(side){sidesOut[side]=(sides[side]||0)+by});return pvc.Sides.updateSize(sidesOut)};pvc.PercentValue=function(pct){this.percent=pct};pvc.PercentValue.prototype.resolve=function(total){return this.percent*total};pvc.PercentValue.parse=function(value){if(value!=null&&value!==''){switch(typeof value){case'number':return value;case'string':var match=value.match(/^(.+?)\s*(%)?$/);if(match){var n=+match[1];if(!isNaN(n)){if(match[2]){if(n>=0){return new pvc.PercentValue(n/100)}}else{return n}}}break;case'object':if(value instanceof pvc.PercentValue){return value}break}if(pvc.debug){pvc.log(def.format("Invalid margins component '{0}'",[''+value]))}}};pvc.PercentValue.resolve=function(value,total){return(value instanceof pvc.PercentValue)?value.resolve(total):value};var markRenderCore=pv.Mark.prototype.renderCore,markZOrder=pv.Mark.prototype.zOrder;pv.Mark.prototype.zOrder=function(zOrder){var borderPanel=this.borderPanel;if(borderPanel&&borderPanel!==this){return markZOrder.call(borderPanel,zOrder)}return markZOrder.call(this,zOrder)};pv.Mark.prototype.renderCore=function(){var root=this.root;root._renderId=(root._renderId||0)+1;if(pvc.debug>=25){pvc.log("BEGIN RENDER "+root._renderId)}markRenderCore.apply(this,arguments);if(pvc.debug>=25){pvc.log("END RENDER "+root._renderId)}};pv.Mark.prototype.renderId=function(){return this.root._renderId};pv.Mark.prototype.wrapper=function(wrapper){this._wrapper=wrapper;return this};pv.Mark.prototype.wrap=function(f,m){if(f&&def.fun.is(f)&&this._wrapper&&!f._cccWrapped){f=this._wrapper(f,m);f._cccWrapped=true}return f};pv.Mark.prototype.lock=function(prop,value){if(value!==undefined){this[prop](value)}(this._locked||(this._locked={}))[prop]=true;return this};pv.Mark.prototype.isIntercepted=function(prop){return this._intercepted&&this._intercepted[prop]};pv.Mark.prototype.isLocked=function(prop){return this._locked&&this._locked[prop]};pv.Mark.prototype.addMargin=function(name,margin){if(margin!==0){var staticValue=def.nullyTo(this.propertyValue(name),0),fMeasure=pv.functor(staticValue);this[name](function(){return margin+fMeasure.apply(this,arraySlice.call(arguments))})}return this};pv.Mark.prototype.addMargins=function(margins){var all=def.get(margins,'all',0);this.addMargin('left',def.get(margins,'left',all));this.addMargin('right',def.get(margins,'right',all));this.addMargin('top',def.get(margins,'top',all));this.addMargin('bottom',def.get(margins,'bottom',all));return this};pv.Mark.prototype.eachInstanceWithData=function(fun,ctx){this.eachInstance(function(scenes,index,t){if(scenes.mark.sign&&scenes[index].data){fun.call(ctx,scenes,index,t)}})};pv.Transform.prototype.transformHPosition=function(left){return this.x+(this.k*left)};pv.Transform.prototype.transformVPosition=function(top){return this.y+(this.k*top)};pv.Transform.prototype.transformLength=function(length){return this.k*length};var Size=def.type('pvc.Size').init(function(width,height){if(arguments.length===1){if(width!=null){this.setSize(width)}}else{if(width!=null){this.width=width}if(height!=null){this.height=height}}}).add({stringify:function(out,remLevels,keyArgs){return pvc.stringifyRecursive(out,def.copyOwn(this),remLevels,keyArgs)},setSize:function(size,keyArgs){if(typeof size==='string'){var comps=size.split(/\s+/).map(function(comp){return pvc.PercentValue.parse(comp)});switch(comps.length){case 1:this.set(def.get(keyArgs,'singleProp','all'),comps[0]);return this;case 2:this.set('width',comps[0]);this.set('height',comps[1]);return this;case 0:return this}}else if(typeof size==='number'){this.set(def.get(keyArgs,'singleProp','all'),size);return this}else if(typeof size==='object'){if(size instanceof pvc.PercentValue){this.set(def.get(keyArgs,'singleProp','all'),size)}else{this.set('all',size.all);for(var p in size){if(p!=='all'){this.set(p,size[p])}}}return this}if(pvc.debug){pvc.log("Invalid 'size' value: "+pvc.stringify(size))}return this},set:function(prop,value){if(value!=null&&(prop==='all'||def.hasOwn(pvc.Size.namesSet,prop))){value=pvc.PercentValue.parse(value);if(value!=null){if(prop==='all'){pvc.Size.names.forEach(function(p){this[p]=value},this)}else{this[prop]=value}}}return this},clone:function(){return new Size(this.width,this.height)},intersect:function(size){return new Size(Math.min(this.width,size.width),Math.min(this.height,size.height))},resolve:function(refSize){var size={};pvc.Size.names.forEach(function(length){var lengthValue=this[length];if(lengthValue!=null){if(typeof(lengthValue)==='number'){size[length]=lengthValue}else if(refSize){var refLength=refSize[length];if(refLength!=null){size[length]=lengthValue.resolve(refLength)}}}},this);return size}});pvc.Size.names=['width','height'];pvc.Size.namesSet=pv.dict(pvc.Size.names,def.retTrue);pvc.Size.toOrtho=function(value,anchor){if(value!=null){var a_ol;if(anchor){a_ol=pvc.BasePanel.orthogonalLength[anchor]}value=pvc.Size.to(value,{singleProp:a_ol});if(anchor){delete value[pvc.BasePanel.oppositeLength[a_ol]]}}return value};pvc.Size.to=function(v,keyArgs){if(v!=null&&!(v instanceof Size)){v=new Size().setSize(v,keyArgs)}return v};var Offset=def.type('pvc.Offset').init(function(x,y){if(arguments.length===1){if(x!=null){this.setOffset(x)}}else{if(x!=null){this.x=x}if(y!=null){this.y=y}}}).add({stringify:function(out,remLevels,keyArgs){return pvc.stringifyRecursive(out,def.copyOwn(this),remLevels,keyArgs)},setOffset:function(offset,keyArgs){if(typeof offset==='string'){var comps=offset.split(/\s+/).map(function(comp){return pvc.PercentValue.parse(comp)});switch(comps.length){case 1:this.set(def.get(keyArgs,'singleProp','all'),comps[0]);return this;case 2:this.set('x',comps[0]);this.set('y',comps[1]);return this;case 0:return this}}else if(typeof offset==='number'){this.set(def.get(keyArgs,'singleProp','all'),offset);return this}else if(typeof offset==='object'){this.set('all',offset.all);for(var p in offset){if(p!=='all'){this.set(p,offset[p])}}return this}if(pvc.debug){pvc.log("Invalid 'offset' value: "+pvc.stringify(offset))}return this},set:function(prop,value){if(value!=null&&def.hasOwn(pvc.Offset.namesSet,prop)){value=pvc.PercentValue.parse(value);if(value!=null){if(prop==='all'){pvc.Offset.names.forEach(function(p){this[p]=value},this)}else{this[prop]=value}}}},resolve:function(refSize){var offset={};pvc.Size.names.forEach(function(length){var offsetProp=pvc.Offset.namesSizeToOffset[length];var offsetValue=this[offsetProp];if(offsetValue!=null){if(typeof(offsetValue)==='number'){offset[offsetProp]=offsetValue}else if(refSize){var refLength=refSize[length];if(refLength!=null){offset[offsetProp]=offsetValue.resolve(refLength)}}}},this);return offset}});pvc.Offset.names=['x','y'];pvc.Offset.namesSet=pv.dict(pvc.Offset.names,def.retTrue);pvc.Offset.namesSizeToOffset={width:'x',height:'y'};pvc.Offset.namesSidesToOffset={left:'x',right:'x',top:'y',bottom:'y'};pvc.Offset.as=function(v){if(v!=null&&!(v instanceof Offset)){v=new Offset().setOffset(v)}return v}}());(function($){$.support.svg=$.support.svg||document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")}(jQuery)); -pvc.text={getFitInfo:function(w,h,text,font,diagMargin){if(text===''){return{h:true,v:true,d:true}}var len=pv.Text.measure(text,font).width;return{h:len<=w,v:len<=h,d:len<=Math.sqrt(w*w+h*h)-diagMargin}},trimToWidthB:function(len,text,font,trimTerminator,before){len-=pv.Text.measure(trimTerminator,font).width;return pvc.text.trimToWidth(len,text,font,trimTerminator,before)},trimToWidth:function(len,text,font,trimTerminator,before){if(text===''){return text}var textLen=pv.Text.measure(text,font).width;if(textLen<=len){return text}if(textLen>len*1.5){return pvc.text.trimToWidthBin(len,text,font,trimTerminator,before)}while(textLen>len){text=before?text.slice(1):text.slice(0,text.length-1);textLen=pv.Text.measure(text,font).width}return before?(trimTerminator+text):(text+trimTerminator)},trimToWidthBin:function(len,text,font,trimTerminator,before){var ilen=text.length,high=ilen-2,low=0,mid,textLen;while(low<=high&&high>0){mid=Math.ceil((low+high)/2);var textMid=before?text.slice(ilen-mid):text.slice(0,mid);textLen=pv.Text.measure(textMid,font).width;if(textLen>len){high=mid-1}else if(pv.Text.measure(before?text.slice(ilen-mid-1):text.slice(0,mid+1),font).widthlineWidth){if(line){lines.push(line)}line=word}else{line=nextLine}}}if(line){lines.push(line)}return lines},getLabelBBox:function(textWidth,textHeight,align,baseline,angle,margin){var polygon=pv.Label.getPolygon(textWidth,textHeight,align,baseline,angle,margin);var bbox=polygon.bbox();bbox.source=polygon;bbox.sourceAngle=angle;bbox.sourceAlign=align;bbox.sourceTextWidth=textWidth;return bbox}}; -def.scope(function(){pvc.color={scale:colorScale,scales:colorScales};function colorScales(keyArgs){keyArgs||def.fail.argumentRequired('keyArgs');var type=keyArgs.type||def.fail.argumentRequired('keyArgs.type');switch(type){case'linear':return new pvc.color.LinearScalesBuild(keyArgs).buildMap();case'discrete':return new pvc.color.DiscreteScalesBuild(keyArgs).buildMap();case'normal':return new pvc.color.NormalScalesBuild(keyArgs).buildMap()}throw def.error.argumentInvalid('scaleType',"Unexistent scale type '{0}'.",[type])}function colorScale(keyArgs){keyArgs||def.fail.argumentRequired('keyArgs');var type=keyArgs.type||def.fail.argumentRequired('keyArgs.type');switch(type){case'linear':return new pvc.color.LinearScalesBuild(keyArgs).build();case'discrete':return new pvc.color.DiscreteScalesBuild(keyArgs).build();case'normal':return new pvc.color.NormalScalesBuild(keyArgs).build()}throw def.error.argumentInvalid('scaleType',"Unexistent scale type '{0}'.",[type])}def.type('pvc.color.ScalesBuild').init(function(keyArgs){this.keyArgs=keyArgs;this.data=keyArgs.data||def.fail.argumentRequired('keyArgs.data');this.domainDimName=keyArgs.colorDimension||def.fail.argumentRequired('keyArgs.colorDimension');this.domainDim=this.data.dimensions(this.domainDimName);var dimType=this.domainDim.type;if(!dimType.isComparable){this.domainComparer=null;pvc.log("Color value dimension should be comparable. Generated color scale may be invalid.")}else{this.domainComparer=function(a,b){return dimType.compare(a,b)}}this.nullRangeValue=keyArgs.colorNull?pv.color(keyArgs.colorNull):pv.Color.transparent;this.domainRangeCountDif=0}).add({build:function(){this.range=this._getRange();this.desiredDomainCount=this.range.length+this.domainRangeCountDif;var domain=this._getDomain();return this._createScale(domain)},buildMap:function(){this.range=this._getRange();this.desiredDomainCount=this.range.length+this.domainRangeCountDif;var createCategoryScale;if(this.keyArgs.normPerBaseCategory){createCategoryScale=function(leafData){var domain=this._ensureDomain(null,false,leafData);return this._createScale(domain)}}else{var domain=this._getDomain(),scale=this._createScale(domain);createCategoryScale=def.fun.constant(scale)}return this._createCategoryScalesMap(createCategoryScale)},_createScale:def.method({isAbstract:true}),_createCategoryScalesMap:function(createCategoryScale){return this.data.children().object({name:function(leafData){return leafData.absKey},value:createCategoryScale,context:this})},_getRange:function(){var keyArgs=this.keyArgs,range=keyArgs.colors||['red','yellow','green'];if(keyArgs.colorMin!=null&&keyArgs.colorMax!=null){range=[keyArgs.colorMin,keyArgs.colorMax]}else if(keyArgs.colorMin!=null){range.unshift(keyArgs.colorMin)}else if(keyArgs.colorMax!=null){range.push(keyArgs.colorMax)}return range.map(function(c){return pv.color(c)})},_getDataExtent:function(data){var extent=data.dimensions(this.domainDimName).extent({visible:true});if(!extent){return null}var min=extent.min.value,max=extent.max.value;if(max==min){if(max>=1){min=max-1}else{max=min+1}}return{min:min,max:max}},_getDomain:function(){var domain=this.keyArgs.colorDomain;if(domain!=null){if(this.domainComparer){domain.sort(this.domainComparer)}if(domain.length>this.desiredDomainCount){domain=domain.slice(0,this.desiredDomainCount)}}else{domain=[]}return this._ensureDomain(domain,true,this.data)},_ensureDomain:function(domain,doDomainPadding,data){var extent;if(domain&&doDomainPadding){var domainPointsMissing=this.desiredDomainCount-domain.length;if(domainPointsMissing>0){extent=this._getDataExtent(data);if(extent){switch(domainPointsMissing){case 1:if(this.domainComparer){def.array.insert(domain,extent.max,this.domainComparer)}else{domain.push(extent.max)}break;case 2:if(this.domainComparer){def.array.insert(domain,extent.min,this.domainComparer);def.array.insert(domain,extent.max,this.domainComparer)}else{domain.unshift(extent.min);domain.push(extent.max)}break;default:if(pvc.debug>=2){pvc.log("Ignoring option 'colorDomain' due to unsupported length."+def.format(" Should have '{0}', but instead has '{1}'.",[this.desiredDomainCount,domain.length]))}domain=null}}}}if(!domain){extent||(extent=this._getDataExtent(data));if(extent){var min=extent.min,max=extent.max;var step=(max-min)/(this.desiredDomainCount-1);domain=pv.range(min,max+step,step)}}return domain}});def.type('pvc.color.LinearScalesBuild',pvc.color.ScalesBuild).add({_createScale:function(domain){var scale=pv.Scale.linear();if(domain){scale.domain.apply(scale,domain)}scale.range.apply(scale,this.range);return scale}});def.type('pvc.color.DiscreteScalesBuild',pvc.color.ScalesBuild).init(function(keyArgs){this.base(keyArgs);this.domainRangeCountDif=1}).add({_createScale:function(domain){var Dl=domain.length-1,range=this.range,nullRangeValue=this.nullRangeValue,Rl=range.length-1;function scale(val){if(val==null){return nullRangeValue}for(var i=0;i=2&&def.hasOwn(_trends,type)){pvc.log(def.format("[WARNING] A trend type with the name '{0}' is already defined.",[type]))}var label=trendSpec.label||def.fail.argumentRequired('trendSpec.label');var model=trendSpec.model||def.fail.argumentRequired('trendSpec.model');def.fun.is(model)||def.fail.argumentInvalid('trendSpec.mode',"Must be a function.");var trendInfo={dataPartAtom:{v:'trend',f:label},type:type,label:label,model:model};_trends[type]=trendInfo},'get',function(type){type||def.fail.argumentRequired('type');return def.getOwn(_trends,type)||def.fail.operationInvalid("Undefined trend type '{0}'.",[type])},'has',function(type){return def.hasOwn(_trends,type)},'types',function(){return def.ownKeys(_trends)});trends.define('linear',{label:'Linear trend',model:function(options){var rows=def.get(options,'rows');var funX=def.get(options,'x');var funY=def.get(options,'y');var i=0;var N=0;var sumX=0;var sumY=0;var sumXY=0;var sumXX=0;var parseNum=function(value){return value!=null?(+value):NaN};while(rows.next()){var row=rows.item;var x=funX?parseNum(funX(row)):i;if(!isNaN(x)){var y=parseNum(funY(row));if(!isNaN(y)){N++;sumX+=x;sumY+=y;sumXY+=x*y;sumXX+=x*x}}i++}var alpha,beta;if(N>=2){var avgX=sumX/N;var avgY=sumY/N;var avgXY=sumXY/N;var avgXX=sumXX/N;var den=(avgXX-avgX*avgX);if(den===0){beta=0}else{beta=(avgXY-(avgX*avgY))/den}alpha=avgY-beta*avgX;return{alpha:alpha,beta:beta,reset:def.noop,sample:function(x){return alpha+beta*(+x)}}}}});trends.define('moving-average',{label:'Moving average',model:function(options){var W=Math.max(+(def.get(options,'periods')||3),2);var sum=0;var avgValues=[];return{reset:function(){sum=0;avgValues.length=0},sample:function(x,y,i){var L=W;if(y!=null){avgValues.unshift(y);sum+=y;L=avgValues.length;if(L>W){sum-=avgValues.pop();L=W}}return sum/L}}}});trends.define('weighted-moving-average',{label:'Weighted Moving average',model:function(options){var W=Math.max(+(def.get(options,'periods')||3),2);var sum=0;var numer=0;var avgValues=[];var L=0;var denom=0;return{reset:function(){sum=numer=denom=L=0;avgValues.length=0},sample:function(x,y){if(y!=null){if(L=col.length){col.push(child)}else{col.splice(index,0,child)}}function data_removeColChild(parent,childrenProp,child,parentProp){(child&&(!child[parentProp]||child[parentProp]===parent))||def.assert("Not a child");var children=parent[childrenProp];if(children){var index=children.indexOf(child);if(index>=0){def.array.removeAt(children,index)}}child[parentProp]=null} -def.type('pvc.data.DimensionType').init(function(complexType,name,keyArgs){this.complexType=complexType;this.name=name;this.label=def.get(keyArgs,'label')||pvc.buildTitleFromName(name);var groupAndLevel=pvc.splitIndexedId(name);this.group=groupAndLevel[0];this.groupLevel=def.nullyTo(groupAndLevel[1],0);if(this.label.indexOf('{')>=0){this.label=def.format(this.label,[this.groupLevel+1])}this.playedVisualRoles=new def.Map();this.isHidden=!!def.get(keyArgs,'isHidden');var valueType=def.get(keyArgs,'valueType')||null;var valueTypeName=pvc.data.DimensionType.valueTypeName(valueType);var cast=def.getOwn(pvc.data.DimensionType.cast,valueTypeName,null);this.valueType=valueType;this.valueTypeName=valueTypeName;this.cast=cast;this.isDiscreteValueType=(this.valueType!==Number&&this.valueType!==Date);this.isDiscrete=def.get(keyArgs,'isDiscrete');if(this.isDiscrete==null){this.isDiscrete=this.isDiscreteValueType}else{this.isDiscrete=!!this.isDiscrete;if(!this.isDiscrete&&this.isDiscreteValueType){throw def.error.argumentInvalid('isDiscrete',"The only supported continuous value types are Number and Date.")}}this._converter=def.get(keyArgs,'converter')||null;if(!this._converter){var rawFormat=def.get(keyArgs,'rawFormat');if(rawFormat){switch(this.valueType){case Date:this._converter=pv.Format.createParser(pv.Format.date(rawFormat));break}}}this._key=def.get(keyArgs,'key')||null;this._comparer=def.get(keyArgs,'comparer');if(this._comparer===undefined){switch(this.valueType){case Number:case Date:this._comparer=def.compare;break;default:this._comparer=null}}this.isComparable=this._comparer!=null;this._formatter=def.get(keyArgs,'formatter')||null;if(!this._formatter){switch(this.valueType){case Number:this._formatter=pv.Format.createFormatter(pv.Format.number().fractionDigits(0,2));break;case Date:var format=def.get(keyArgs,'format');if(!format){format=def.get(keyArgs,'rawFormat');if(format){format=format.replace(/-/g,"/")}}if(!format){format="%Y/%m/%d"}this._formatter=pv.Format.createFormatter(pv.Format.date(format));break}}}).add({isCalculated:false,compare:function(a,b){if(a==null){if(b==null){return 0}return-1}else if(b==null){return 1}return this._comparer.call(null,a,b)},comparer:function(reverse){if(!this.isComparable){return null}var me=this;if(reverse){return this._reverseComparer||(this._reverseComparer=function(a,b){return me.compare(b,a)})}return this._directComparer||(this._directComparer=function(a,b){return me.compare(a,b)})},atomComparer:function(reverse){if(reverse){return this._reverseAtomComparer||(this._reverseAtomComparer=this._createReverseAtomComparer())}return this._directAtomComparer||(this._directAtomComparer=this._createDirectAtomComparer())},_toDiscrete:function(){this.isDiscrete=true},_toCalculated:function(){this.isCalculated=true},_createReverseAtomComparer:function(){if(!this.isComparable){return atom_idComparerReverse}var me=this;function reverseAtomComparer(a,b){if(a===b){return 0}return me.compare(b.value,a.value)}return reverseAtomComparer},_createDirectAtomComparer:function(){if(!this.isComparable){return atom_idComparer}var me=this;function directAtomComparer(a,b){if(a===b){return 0}return me.compare(a.value,b.value)}return directAtomComparer},formatter:function(){return this._formatter},converter:function(){return this._converter},playingPercentVisualRole:function(){return def.query(this.playedVisualRoles.values()).any(function(visualRole){return visualRole.isPercent})}});pvc.data.DimensionType.cast={'Date':function(value){return value instanceof Date?value:new Date(value)},'Number':function(value){value=Number(value);return isNaN(value)?null:value},'String':String,'Boolean':Boolean,'Object':Object,'Any':null};pvc.data.DimensionType.dimensionGroupName=function(dimName){return dimName.replace(/^(.*?)(\d*)$/,"$1")};pvc.data.DimensionType.valueTypeName=function(valueType){if(valueType==null){return"Any"}switch(valueType){case Boolean:return'Boolean';case Number:return'Number';case String:return'String';case Object:return'Object';case Date:return'Date';default:throw def.error.argumentInvalid('valueType',"Invalid valueType function: '{0}'.",[valueType])}};pvc.data.DimensionType.extendSpec=function(dimName,dimSpec,keyArgs){var dimGroup=pvc.data.DimensionType.dimensionGroupName(dimName),userDimGroupsSpec=def.get(keyArgs,'dimensionGroups');if(userDimGroupsSpec){var groupDimSpec=userDimGroupsSpec[dimGroup];if(groupDimSpec){dimSpec=def.create(groupDimSpec,dimSpec)}}if(!dimSpec){dimSpec={}}switch(dimGroup){case'category':var isCategoryTimeSeries=def.get(keyArgs,'isCategoryTimeSeries',false);if(isCategoryTimeSeries){if(dimSpec.valueType===undefined){dimSpec.valueType=Date}}break;case'value':if(dimSpec.valueType===undefined){dimSpec.valueType=Number}if(dimSpec.valueType===Number){if(dimSpec.formatter===undefined&&!dimSpec.format){dimSpec.formatter=def.get(keyArgs,'valueNumberFormatter')}}break}if(dimSpec.converter===undefined&&dimSpec.valueType===Date&&!dimSpec.rawFormat){dimSpec.rawFormat=def.get(keyArgs,'timeSeriesFormat')}return dimSpec};function dimType_addVisualRole(visualRole){this.playedVisualRoles.set(visualRole.name,visualRole);compType_dimensionRolesChanged.call(this.type,this)}function dimType_removeVisualRole(visualRole){this.playedVisualRoles.rem(visualRole.name);compType_dimensionRolesChanged.call(this.type,this)} -def.type('pvc.data.ComplexType').init(function(dimTypeSpecs){this._dims={};this._dimsList=[];this._dimsNames=[];this._calculations=[];this._calculatedDimNames={};this._dimsIndexByName=null;this._dimsByGroup={};this._dimsNamesByGroup={};if(dimTypeSpecs){for(var name in dimTypeSpecs){this.addDimension(name,dimTypeSpecs[name])}}}).add({describe:function(){var out=["COMPLEX TYPE INFORMATION",pvc.logSeparator];this._dimsList.forEach(function(type){var features=[];features.push(type.valueTypeName);if(type.isComparable){features.push("comparable")}if(!type.isDiscrete){features.push("continuous")}if(type.isHidden){features.push("hidden")}out.push(" "+type.name+" ("+features.join(', ')+")")});return out.join("\n")},dimensions:function(name,keyArgs){if(name==null){return this._dims}var dimType=def.getOwn(this._dims,name,null);if(!dimType&&def.get(keyArgs,'assertExists',true)){throw def.error.argumentInvalid('name',"Undefined dimension '{0}'",[name])}return dimType},dimensionsList:function(){return this._dimsList},calculatedDimensionsList:function(){return this._calcDimsList},dimensionsNames:function(){return this._dimsNames},groupDimensions:function(group,keyArgs){var dims=def.getOwn(this._dimsByGroup,group);if(!dims&&def.get(keyArgs,'assertExists',true)){throw def.error.operationInvalid("There is no dimension type group with name '{0}'.",[group])}return dims},groupDimensionsNames:function(group,keyArgs){var dimNames=def.getOwn(this._dimsNamesByGroup,group);if(!dimNames&&def.get(keyArgs,'assertExists',true)){throw def.error.operationInvalid("There is no dimension type group with name '{0}'.",[group])}return dimNames},addDimension:function(name,dimTypeSpec){name||def.fail.argumentRequired('name');!def.hasOwn(this._dims,name)||def.fail.operationInvalid("A dimension type with name '{0}' is already defined.",[name]);var dimension=new pvc.data.DimensionType(this,name,dimTypeSpec);this._dims[name]=dimension;this._dimsIndexByName=null;var group=dimension.group;var groupLevel;if(group){var groupDims=def.getOwn(this._dimsByGroup,group),groupDimsNames;if(!groupDims){groupDims=this._dimsByGroup[group]=[];groupDimsNames=this._dimsNamesByGroup[group]=[]}else{groupDimsNames=this._dimsNamesByGroup[group]}groupLevel=def.array.insert(groupDimsNames,name,def.compare);groupLevel=~groupLevel;def.array.insertAt(groupDims,groupLevel,dimension)}var index;var L=this._dimsList.length;if(!group){index=L}else{groupLevel=dimension.groupLevel;for(var i=0;igroupLevel){index=i;break}index=i+1}}if(index==null){index=L}}def.array.insertAt(this._dimsList,index,dimension);def.array.insertAt(this._dimsNames,index,name);if(dimension._calculate){index=def.array.binarySearch(this._calcDimsList,dimension._calculationOrder,def.compare,function(dimType){return dimType._calculationOrder});if(index>=0){index++}else{index=~index}def.array.insertAt(this._calcDimsList,index,dimension)}this._isPctRoleDimTypeMap=null;return dimension},addCalculation:function(calcSpec,dimsOptions){calcSpec||def.fail.argumentRequired('calcSpec');var calculation=calcSpec.calculation||def.fail.argumentRequired('calculations[i].calculation');var dimNames=calcSpec.names;if(typeof dimNames==='string'){dimNames=dimNames.split(/\s*\,\s*/)}else{dimNames=def.array.as(dimNames)}if(dimNames&&dimNames.length){var calcDimNames=this._calculatedDimNames;dimNames.forEach(function(name){if(name){name=name.replace(/^\s*(.+?)\s*$/,"$1");!def.hasOwn(calcDimNames,name)||def.fail.argumentInvalid('calculations[i].names',"Dimension name '{0}' is already being calculated.",[name]);var dimType=this._dims[name];if(!dimType){var dimSpec=pvc.data.DimensionType.extendSpec(name,null,dimsOptions);this.addDimension(name,dimSpec)}calcDimNames[name]=true;dimType._toCalculated()}},this)}this._calculations.push(calculation)},isCalculated:function(dimName){return def.hasOwn(this._calculatedDimNames,dimName)},_calculate:function(complex){var calcs=this._calculations;if(calcs.length){var valuesByName={};calcs.forEach(function(calc){calc(complex,valuesByName)});return valuesByName}},getPlayingPercentVisualRoleDimensionMap:function(){var map=this._isPctRoleDimTypeMap;if(!map){map=this._isPctRoleDimTypeMap=new def.Map(def.query(def.own(this._dims)).where(function(dimType){return dimType.playingPercentVisualRole()}).object({name:function(dimType){return dimType.name}}))}return map},sortDimensionNames:function(dims,nameKey){var dimsIndexByName=this._dimsIndexByName;if(!dimsIndexByName){dimsIndexByName=def.query(this._dimsList).object({name:function(dim){return dim.name},value:function(dim,index){return index}});this._dimsIndexByName=dimsIndexByName}dims.sort(function(da,db){return def.compare(dimsIndexByName[nameKey?nameKey(da):da],dimsIndexByName[nameKey?nameKey(db):db])});return dims}});function compType_dimensionRolesChanged(dimType){this._isPctRoleDimTypeMap=null} -def.type('pvc.data.ComplexTypeProject').init(function(dimGroupSpecs){this._dims={};this._dimList=[];this._dimGroupsDims={};this._dimGroupSpecs=dimGroupSpecs||{};this._calcList=[]}).add({_ensureDim:function(name){name||def.fail.argumentInvalid('name',"Invalid dimension name '{0}'.",[name]);var info=def.getOwn(this._dims,name);if(!info){info=this._dims[name]=this._createDim(name);this._dimList.push(info);var groupDimsNames=def.array.lazy(this._dimGroupsDims,info.groupName);def.array.insert(groupDimsNames,name,def.compare)}return info},hasDim:function(name){return def.hasOwn(this._dims,name)},setDim:function(name,spec){var _=this._ensureDim(name).spec;if(spec){def.copy(_,spec)}return this},setDimDefaults:function(name,spec){def.setUDefaults(this._ensureDim(name).spec,spec);return this},_createDim:function(name,spec){var dimGroupName=pvc.data.DimensionType.dimensionGroupName(name);var dimGroupSpec=this._dimGroupSpecs[dimGroupName];if(dimGroupSpec){spec=def.create(dimGroupSpec,spec)}return{name:name,groupName:dimGroupName,spec:spec||{}}},readDim:function(name){var info=this._ensureDim(name);if(info.isRead){throw def.error.operationInvalid("Dimension '{0}' already is the target of a reader.",[name])}if(info.isCalc){throw def.error.operationInvalid("Dimension '{0}' is being calculated, so it cannot be the target of a reader.",[name])}info.isRead=true},calcDim:function(name){var info=this._ensureDim(name);if(info.isCalc){throw def.error.operationInvalid("Dimension '{0}' already is being calculated.",[name])}if(info.isRead){throw def.error.operationInvalid("Dimension '{0}' is the target of a reader, so it cannot be calculated.",[name])}info.isCalc=true},isReadOrCalc:function(name){if(name){var info=def.getOwn(this._dims,name);if(info){return info.isRead||info.isCalc}}return false},groupDimensionsNames:function(groupDimName){return this._dimGroupsDims[groupDimName]},setCalc:function(calcSpec){calcSpec||def.fail.argumentRequired('calculations[i]');calcSpec.calculation||def.fail.argumentRequired('calculations[i].calculation');var dimNames=calcSpec.names;if(typeof dimNames==='string'){dimNames=dimNames.split(/\s*\,\s*/)}else{dimNames=def.array.as(dimNames)}if(dimNames&&dimNames.length){dimNames.forEach(this.calcDim,this)}this._calcList.push(calcSpec)},configureComplexType:function(complexType,translOptions){this._dimList.forEach(function(dimInfo){var dimName=dimInfo.name;var spec=dimInfo.spec;spec=pvc.data.DimensionType.extendSpec(dimName,spec,translOptions);complexType.addDimension(dimName,spec)});this._calcList.forEach(function(calcSpec){complexType.addCalculation(calcSpec)})}}); -def.type('pvc.data.TranslationOper').init(function(chart,complexTypeProj,source,metadata,options){this.chart=chart;this.complexTypeProj=complexTypeProj;this.source=source;this.metadata=metadata||{};this.options=options||{};this._initType();if(pvc.debug>=4){this._logItems=true;this._logItemCount=0}}).add({_logItems:false,logSource:def.method({isAbstract:true}),virtualItemSize:function(){return this.metadata.length},freeVirtualItemSize:function(){return this.virtualItemSize()-this._userUsedIndexesCount},defReader:function(dimReaderSpec){dimReaderSpec||def.fail.argumentRequired('readerSpec');var dimNames;if(typeof dimReaderSpec==='string'){dimNames=dimReaderSpec}else{dimNames=dimReaderSpec.names}if(typeof dimNames==='string'){dimNames=dimNames.split(/\s*\,\s*/)}else{dimNames=def.array.as(dimNames)}var indexes=def.array.as(dimReaderSpec.indexes);if(indexes){indexes.forEach(this._userUseIndex,this)}var hasDims=!!(dimNames&&dimNames.length);var reader=dimReaderSpec.reader;if(!reader){if(hasDims){return this._userCreateReaders(dimNames,indexes)}}else{hasDims||def.fail.argumentRequired('reader.names',"Required argument when a reader function is specified.");this._userRead(reader,dimNames)}return indexes},configureType:function(){this._configureTypeCore()},_configureTypeCore:def.method({isAbstract:true}),_initType:function(){this._userDimsReaders=[];this._userDimsReadersByDim={};this._userItem=[];this._userUsedIndexes={};this._userUsedIndexesCount=0;var userDimReaders=this.options.readers;if(userDimReaders){userDimReaders.forEach(this.defReader,this)}var multiChartIndexes=pvc.parseDistinctIndexArray(this.options.multiChartIndexes);if(multiChartIndexes){this._multiChartIndexes=this.defReader({names:'multiChart',indexes:multiChartIndexes})}},_userUseIndex:function(index){index=+index;(index>=0)||def.fail.argumentInvalid('index',"Invalid reader index: '{0}'.",[index]);!def.hasOwn(this._userUsedIndexes,index)||def.fail.argumentInvalid('index',"Virtual item index '{0}' is already assigned.",[index]);this._userUsedIndexes[index]=true;this._userUsedIndexesCount++;this._userItem[index]=true;return index},_userCreateReaders:function(dimNames,indexes){if(!indexes){indexes=[]}else{indexes.forEach(function(index,j){indexes[j]=+index})}var I=indexes.length,N=dimNames.length,dimName;if(N>I){var nextIndex=I>0?(indexes[I-1]+1):0;do{nextIndex=this._nextAvailableItemIndex(nextIndex);indexes[I]=nextIndex;this._userUseIndex(nextIndex);I++}while(N>I)}var L=(I===N)?N:(N-1);for(var n=0;n read: '+pvc.stringify(atoms))}return valuesByDimName},_propGet:function(dimName,prop){function propGet(item,atoms){atoms[dimName]=item[prop]}return propGet},_constGet:function(dimName,constRawValue,keyArgs){var me=this,constAtom;function constGet(item,atoms){atoms[dimName]=constAtom||(constAtom=me.data.dimensions(dimName).intern(constRawValue))}return constGet},_nextAvailableItemIndex:function(index,L){if(index==null){index=0}if(L==null){L=Infinity}while(index0;i++){var row=source[i];var m=0;while(m10){out.push(' ...')}out.push("COLS ("+this.J+")");var colTypes=this._columnTypes;this.metadata.forEach(function(col,j){out.push(" ["+j+"] "+"'"+col.colName+"' ("+"type: "+col.colType+", "+"inspected: "+(colTypes[j]?'continuous':'discrete')+(col.colLabel?(", label: '"+col.colLabel+"'"):"")+")")});pvc.log(out.join('\n'))},_createPlot2SeriesKeySet:function(plot2SeriesIndexes,seriesKeys){var plot2SeriesKeySet=null,seriesCount=seriesKeys.length;def.query(plot2SeriesIndexes).each(function(indexText){var seriesIndex=+indexText;if(isNaN(seriesIndex)){throw def.error.argumentInvalid('plot2SeriesIndexes',"Element is not a number '{0}'.",[indexText])}if(seriesIndex<0){if(seriesIndex<=-seriesCount){throw def.error.argumentInvalid('plot2SeriesIndexes',"Index is out of range '{0}'.",[seriesIndex])}seriesIndex=seriesCount+seriesIndex}else if(seriesIndex>=seriesCount){throw def.error.argumentInvalid('plot2SeriesIndexes',"Index is out of range '{0}'.",[seriesIndex])}if(!plot2SeriesKeySet){plot2SeriesKeySet={}}plot2SeriesKeySet[seriesKeys[seriesIndex]]=true});return plot2SeriesKeySet},_dataPartGet:function(calcAxis2SeriesKeySet,seriesReader){var me=this;var dataPartDimName=this.options.dataPartDimName;var dataPartDimension,plot2SeriesKeySet,part1Atom,part2Atom,outAtomsSeries={};function dataPartGet(item,outAtoms){if(!dataPartDimension){plot2SeriesKeySet=calcAxis2SeriesKeySet();dataPartDimension=me.data.dimensions(dataPartDimName);if(pvc.debug>=3&&plot2SeriesKeySet){pvc.log("Second axis series values: "+pvc.stringify(def.keys(plot2SeriesKeySet)))}}var partAtom;seriesReader(item,outAtomsSeries);var series=outAtomsSeries.series;if(series!=null&&series.v!=null){series=series.v}if(def.hasOwn(plot2SeriesKeySet,series)){partAtom=part2Atom||(part2Atom=dataPartDimension.intern("1"))}else{partAtom=part1Atom||(part1Atom=dataPartDimension.intern("0"))}outAtoms[dataPartDimName]=partAtom}return dataPartGet}}); -def.type('pvc.data.CrosstabTranslationOper',pvc.data.MatrixTranslationOper).add({virtualItemSize:function(){return this.R+this.C+this.M},_executeCore:function(){if(!this.metadata.length){return def.query()}var dimsReaders=this._getDimensionsReaders();var item=new Array(this.virtualItemSize()),itemCrossGroupIndex=this._itemCrossGroupIndex,me=this;function updateVItemCrossGroup(crossGroupId,source){var itemIndex=itemCrossGroupIndex[crossGroupId],sourceIndex=0,depth=me[crossGroupId];while((depth--)>0){item[itemIndex++]=source[sourceIndex++]}}function updateVItemMeasure(line,cg){var itemIndex=itemCrossGroupIndex.M;var cgIndexes=me._colGroupsIndexes[cg];var depth=me.M;for(var i=0;i0){if(!measuresInColumns){this._colGroups=encodedColGroups;this._colGroupsIndexes=[];this._colGroups.forEach(function(colGroup,cg){this._colGroups[cg]=this._splitEncodedColGroupCell(colGroup);this._colGroupsIndexes[cg]=[this.R+cg]},this);itemCrossGroupTypes.M=[this._columnTypes[this.R]]}else{this.measuresDirection='columns';this._processEncodedColGroups(encodedColGroups)}this.C=this._colGroups[0].length;itemCrossGroupTypes.C=def.array.create(this.C,0)}else{this.C=this.M=0;itemCrossGroupTypes.M=itemCrossGroupTypes.C=[]}}else{this.measuresDirection='rows';this.R=+this.options.measuresIndex;var measuresCount=this.options.measuresCount;if(measuresCount==null){measuresCount=1}this.M=measuresCount;this._colGroups=colNames.slice(this.R+1);this._colGroups.forEach(function(colGroup,cg){this._colGroups[cg]=[colGroup]},this)}}itemCrossGroupTypes.R=this._columnTypes.slice(0,this.R);var seriesInRows=this.options.seriesInRows;var itemGroupIndex=this._itemCrossGroupIndex={'C':!seriesInRows?0:this.R,'R':!seriesInRows?this.C:0,'M':this.C+this.R};var itemTypes=this._itemTypes=new Array(this.virtualItemSize());def.eachOwn(itemGroupIndex,function(groupStartIndex,crossGroup){itemCrossGroupTypes[crossGroup].forEach(function(type,groupIndex){itemTypes[groupStartIndex+groupIndex]=type})});this._itemLogicalGroup={'series':seriesInRows?this.R:this.C,'category':seriesInRows?this.C:this.R,'value':this.M};this._itemLogicalGroupIndex={'series':0,'category':this._itemLogicalGroup.series,'value':this.C+this.R};if(pvc.debug>=3){pvc.log("Crosstab translator "+pvc.stringify({R:this.R,C:this.C,M:this.M}))}},_getCategoriesCount:function(){var R=this.options.categoriesCount;if(R!=null&&(!isFinite(R)||R<0)){R=null}if(R==null){R=def.query(this._columnTypes).whayl(function(type){return type===0}).count();if(!R){R=1}}return R},_splitEncodedColGroupCell:function(colGroup){var values=colGroup.v;var labels;if(values==null){values=[]}else{values=values.split(this._separator);labels=colGroup.f;if(labels){labels=labels.split(this._separator)}}return values.map(function(value,index){return{v:value,f:labels&&labels[index]}})},_processEncodedColGroups:function(encodedColGroups){var L=encodedColGroups.length||def.assert("Must have columns"),R=this.R,colGroups=[],currColGroup,measuresInfo={},measuresInfoList=[];for(var i=0;imeaInfo.groupIndex){meaInfo.groupIndex=currMeaIndex}}measuresInfoList.sort(function(meaInfoA,meaInfoB){return def.compare(meaInfoA.groupIndex,meaInfoB.groupIndex)||def.compare(meaInfoA.index,meaInfoB.index)});var M=measuresInfoList.length;var meaTypes=new Array(M);this._itemCrossGroupTypes.M=meaTypes;measuresInfoList.forEach(function(meaInfoA,index){meaInfoA.groupIndex=index;meaTypes[index]=meaInfoA.type});var CG=colGroups.length,colGroupsValues=new Array(CG),colGroupsIndexes=new Array(CG);colGroups.map(function(colGroup,cg){colGroupsValues[cg]=colGroup.values;var colGroupStartIndex=colGroup.startIndex;var meaIndexes=colGroupsIndexes[cg]=new Array(M);colGroup.measureNames.forEach(function(meaName2,localMeaIndex){var meaIndex=measuresInfo[meaName2].groupIndex;meaIndexes[meaIndex]=R+colGroupStartIndex+localMeaIndex})});this._colGroups=colGroupsValues;this._colGroupsIndexes=colGroupsIndexes;this.M=M},configureType:function(){if(this.measuresDirection==='rows'){throw def.error.notImplemented()}this.base()},_configureTypeCore:function(){var me=this;var itemLogicalGroup=me._itemLogicalGroup;var itemLogicalGroupIndex=me._itemLogicalGroupIndex;var index=0;var dimsReaders=[];function add(dimGroupName,level,count){var crossEndIndex=itemLogicalGroupIndex[dimGroupName]+count;while(count>0){var dimName=pvc.buildIndexedId(dimGroupName,level);if(!me.complexTypeProj.isReadOrCalc(dimName)){index=me._nextAvailableItemIndex(index);if(index>=crossEndIndex){return}dimsReaders.push({names:dimName,indexes:index});index++;count--}level++}}var dataPartDimName=this.options.dataPartDimName;if(dataPartDimName&&this.C===1&&!this.complexTypeProj.isReadOrCalc(dataPartDimName)){var plot2SeriesIndexes=this.options.plot2SeriesIndexes;if(plot2SeriesIndexes!=null){var seriesKeys=this._colGroups.map(function(colGroup){return''+colGroup[0].v});this._plot2SeriesKeySet=this._createPlot2SeriesKeySet(plot2SeriesIndexes,seriesKeys)}}['series','category','value'].forEach(function(dimGroupName){var L=itemLogicalGroup[dimGroupName];if(L>0){add(dimGroupName,0,L)}});if(dimsReaders){dimsReaders.forEach(this.defReader,this)}if(this._plot2SeriesKeySet){var seriesReader=this._userDimsReadersByDim.series;if(seriesReader){var calcAxis2SeriesKeySet=def.fun.constant(this._plot2SeriesKeySet);this._userRead(this._dataPartGet(calcAxis2SeriesKeySet,seriesReader),dataPartDimName)}}}}); -def.type('pvc.data.RelationalTranslationOper',pvc.data.MatrixTranslationOper).add({M:0,C:0,S:0,_processMetadata:function(){this.base();var metadata=this.metadata;var J=this.J;var C=this.options.categoriesCount;if(C!=null&&(!isFinite(C)||C<0)){C=0}var S;var valuesColIndexes,M;if(this.options.isMultiValued){valuesColIndexes=pvc.parseDistinctIndexArray(this.options.measuresIndexes,J-1);M=valuesColIndexes?valuesColIndexes.length:0}var D;if(M==null){if(J>0&&J<=3&&(C==null||C===1)&&S==null){M=1;valuesColIndexes=[J-1];C=J>=2?1:0;S=J>=3?1:0;D=C+S}else if(C!=null&&C>=J){D=J;C=J;S=0;M=0}else{var Mmax=C!=null?(J-C):Infinity;valuesColIndexes=def.query(metadata).where(function(colDef,index){return this._columnTypes[index]!==0},this).select(function(colDef){return colDef.colIndex}).take(Mmax).array();M=valuesColIndexes.length}}if(D==null){D=J-M;if(D===0){S=C=0}else if(C!=null){if(C>D){C=D;S=0}else{S=D-C}}else{S=D>1?1:0;C=D-S}}var seriesInRows=this.options.seriesInRows;var colGroupSpecs=[];if(D){if(S&&!seriesInRows){colGroupSpecs.push({name:'S',count:S})}if(C){colGroupSpecs.push({name:'C',count:C})}if(S&&seriesInRows){colGroupSpecs.push({name:'S',count:S})}}if(M){colGroupSpecs.push({name:'M',count:M})}var availableInputIndexes=def.range(0,J).array();if(valuesColIndexes){valuesColIndexes.forEach(function(inputIndex){availableInputIndexes.splice(inputIndex,1)})}var specsByName={};colGroupSpecs.forEach(function(groupSpec){var count=groupSpec.count;var name=groupSpec.name;specsByName[name]=groupSpec;if(valuesColIndexes&&name==='M'){groupSpec.indexes=valuesColIndexes}else{groupSpec.indexes=availableInputIndexes.splice(0,count)}},this);this.M=M;this.S=S;this.C=C;var itemPerm=[];['S','C','M'].forEach(function(name){var groupSpec=specsByName[name];if(groupSpec){def.array.append(itemPerm,groupSpec.indexes)}});var colTypes=this._columnTypes;this._itemTypes=itemPerm.map(function(index){return colTypes[index]});this._itemCrossGroupIndex={S:0,C:this.S,M:this.S+this.C};this._itemPerm=itemPerm;if(pvc.debug>=3){var out=["RELATIONAL TRANSLATOR MAPPING",pvc.logSeparator,"["+colGroupSpecs.map(function(groupSpec){return def.array.create(groupSpec.count,groupSpec.name).join('')}).join(' ')+"]"];pvc.log(out.join("\n"))}},_configureTypeCore:function(){var me=this;var index=0;var dimsReaders=[];function add(dimGroupName,colGroupName,level,count){var groupEndIndex=me._itemCrossGroupIndex[colGroupName]+count;while(count>0){var dimName=pvc.buildIndexedId(dimGroupName,level);if(!me.complexTypeProj.isReadOrCalc(dimName)){index=me._nextAvailableItemIndex(index);if(index>=groupEndIndex){return}dimsReaders.push({names:dimName,indexes:index});index++;count--}level++}}if(this.S>0){add('series','S',0,this.S)}if(this.C>0){add('category','C',0,this.C)}if(this.M>0){add('value','M',0,this.M)}if(dimsReaders){dimsReaders.forEach(this.defReader,this)}var plot2SeriesIndexes=this.options.plot2SeriesIndexes;if(plot2SeriesIndexes!=null){var seriesReader=this._userDimsReadersByDim.series;if(seriesReader){var dataPartDimName=this.options.dataPartDimName;this._userRead(relTransl_dataPartGet.call(this,plot2SeriesIndexes,seriesReader),dataPartDimName)}}},_executeCore:function(){var dimsReaders=this._getDimensionsReaders();var permIndexes=this._itemPerm;return def.query(this._getItems()).select(function(item){item=pv.permute(item,permIndexes);return this._readItem(item,dimsReaders)},this)}});function relTransl_dataPartGet(plot2SeriesIndexes,seriesReader){var me=this;function calcAxis2SeriesKeySet(){var atoms={};var seriesKeys=def.query(me.source).select(function(item){seriesReader(item,atoms);var value=atoms.series;if(value!=null&&value.v!=null){value=value.v}return value||null}).distinct().array();return me._createPlot2SeriesKeySet(plot2SeriesIndexes,seriesKeys)}return this._dataPartGet(calcAxis2SeriesKeySet,seriesReader)} -def.type('pvc.data.Atom').init(function(dimension,value,label,rawValue,key){this.dimension=dimension;this.id=(value==null?-def.nextId():def.nextId());this.value=value;this.label=label;if(rawValue!==undefined){this.rawValue=rawValue}this.key=key}).add({isVirtual:false,rawValue:undefined,toString:function(){var label=this.label;if(label!=null){return label}label=this.value;return label!=null?(""+label):""}});function atom_idComparer(a,b){return a.id-b.id}function atom_idComparerReverse(a,b){return b.id-a.id} -var complex_nextId=1;def.type('pvc.data.Complex').init(function(source,atomsByName,dimNames,atomsBase,wantLabel,calculate){this.id=complex_nextId++;var owner;if(source){owner=source.owner;if(!atomsBase){atomsBase=source.atoms}}this.owner=owner||this;this.atoms=atomsBase?Object.create(atomsBase):{};var hadDimNames=!!dimNames;if(!dimNames){dimNames=owner.type._dimsNames}var atomsMap=this.atoms;var D=dimNames.length;var i,dimName;if(atomsByName){var ownerDims=owner._dimensions;var addAtom=function(dimName,value){if(value!=null){var dimension=def.getOwn(ownerDims,dimName);var atom=dimension.intern(value);if(!atomsBase||atom!==atomsBase[dimName]){atomsMap[dimName]=atom}}};if(!hadDimNames){for(dimName in atomsByName){addAtom(dimName,atomsByName[dimName])}}else{for(i=0;i0},atoms:function(keyArgs){if(this._lazyInit){this._lazyInit()}var visible=def.get(keyArgs,'visible');if(visible==null){return this._atoms}visible=!!visible;this._visibleAtoms||(this._visibleAtoms={});return this._visibleAtoms[visible]||(this._visibleAtoms[visible]=dim_calcVisibleAtoms.call(this,visible))},indexes:function(keyArgs){if(this._lazyInit){this._lazyInit()}var visible=def.get(keyArgs,'visible');if(visible==null){return pv.range(0,this._atoms.length)}visible=!!visible;this._visibleIndexes||(this._visibleIndexes={});return this._visibleIndexes[visible]||(this._visibleIndexes[visible]=dim_calcVisibleIndexes.call(this,visible))},atom:function(value){if(value==null||value===''){return this._nullAtom}if(value instanceof pvc.data.Atom){return value}if(this._lazyInit){this._lazyInit()}var key=this.type._key?this.type._key.call(null,value):value;return this._atomsByKey[key]||null},extent:function(keyArgs){var atoms=this.atoms(keyArgs);var L=atoms.length;if(!L){return undefined}var offset=this._nullAtom&&atoms[0].value==null?1:0;var countWithoutNull=L-offset;if(countWithoutNull>0){var min=atoms[offset];var max=atoms[L-1];var tmp;if(min!==max&&def.get(keyArgs,'abs',false)){var minSign=min.value<0?-1:1;var maxSign=max.value<0?-1:1;if(minSign===maxSign){if(maxSign<0){tmp=max;max=min;min=tmp}}else if(countWithoutNull>2){if(max.value<-min.value){max=min}var zeroIndex=def.array.binarySearch(atoms,0,this.type.comparer(),function(a){return a.value});if(zeroIndex<0){zeroIndex=~zeroIndex;var negAtom=atoms[zeroIndex-1];var posAtom=atoms[zeroIndex];if(-negAtom.valueoffset)?atoms[offset]:undefined},max:function(keyArgs){var atoms=this.atoms(keyArgs);var L=atoms.length;return L&&atoms[L-1].value!=null?atoms[L-1]:undefined},sum:function(keyArgs){var isAbs=!!def.get(keyArgs,'abs',false),zeroIfNone=def.get(keyArgs,'zeroIfNone',true),key=dim_buildDatumsFilterKey(keyArgs)+':'+isAbs;var sum=def.getOwn(this._sumCache,key);if(sum===undefined){var dimName=this.name;sum=this.data.datums(null,keyArgs).reduce(function(sum2,datum){var value=datum.atoms[dimName].value;if(isAbs&&value<0){value=-value}return sum2!=null?(sum2+value):value},null);(this._sumCache||(this._sumCache={}))[key]=sum}return zeroIfNone?(sum||0):sum},percent:function(atomOrValue,keyArgs){var value=(atomOrValue instanceof pvc.data.Atom)?atomOrValue.value:atomOrValue;if(!value){return 0}var sum=this.sum(def.create(keyArgs,{abs:true}));return sum?(Math.abs(value)/sum):0},percentOverParent:function(keyArgs){var value=this.sum(keyArgs);if(!value){return 0}var parentData=this.data.parent;if(!parentData){return 0}var sum=parentData.dimensionsSumAbs(this.name,keyArgs);return sum?(Math.abs(value)/sum):0},format:function(value,sourceValue){return""+(this.type._formatter?this.type._formatter.call(null,value,sourceValue):"")},intern:function(sourceValue,isVirtual){if(sourceValue==null||sourceValue===''){return this._nullAtom||dim_createNullAtom.call(this,sourceValue)}if(sourceValue instanceof pvc.data.Atom){if(sourceValue.dimension!==this){throw def.error.operationInvalid("Atom is of a different dimension.")}return sourceValue}var value,label;var type=this.type;if(typeof sourceValue==='object'&&('v'in sourceValue)){label=sourceValue.f;sourceValue=sourceValue.v}if(!isVirtual){var converter=type._converter;value=converter?converter(sourceValue):sourceValue;if(value==null||value===''){return this._nullAtom||dim_createNullAtom.call(this,sourceValue)}}else{value=sourceValue}var cast=type.cast;if(cast){value=cast(value);if(value==null||value===''){return this._nullAtom||dim_createNullAtom.call(this)}}var keyFun=type._key;var key=''+(keyFun?keyFun(value):value);key||def.fail.operationInvalid("Only a null value can have an empty key.");var atom=this._atomsByKey[key];if(atom){if(!isVirtual&&atom.isVirtual){delete atom.isVirtual}return atom}return dim_createAtom.call(this,type,sourceValue,key,value,label,isVirtual)},dispose:function(){if(!this._disposed){data_disposeChildList(this._children,'parent');data_disposeChildList(this._linkChildren,'linkParent');if(this.parent){dim_removeChild.call(this.parent,this)}if(this.linkParent){dim_removeLinkChild.call(this.linkParent,this)}dim_clearVisiblesCache.call(this);this._lazyInit=null;this._atoms=this._nullAtom=this._virtualNullAtom=null;this._disposed=true}}});function dim_createAtom(type,sourceValue,key,value,label,isVirtual){var atom;if(this.owner===this){if(label==null){var formatter=type._formatter;if(formatter){label=formatter(value,sourceValue)}else{label=value}}label=""+label;if(!label&&pvc.debug>=2){pvc.log("Only the null value should have an empty label.")}atom=new pvc.data.Atom(this,value,label,sourceValue,key);if(isVirtual){atom.isVirtual=true}}else{var source=this.parent||this.linkParent;atom=source._atomsByKey[key]||dim_createAtom.call(source,type,sourceValue,key,value,label,isVirtual)}def.array.insert(this._atoms,atom,this._atomComparer);dim_clearVisiblesCache.call(this);this._atomsByKey[key]=atom;return atom}function dim_internAtom(atom){var key=atom.key;if(atom.dimension===this){(this.owner===this)||def.assert("Should be an owner dimension");if(!key&&atom===this._virtualNullAtom){atom=this.intern(null)}return atom}if(!this._lazyInit){var localAtom=this._atomsByKey[key];if(localAtom){if(localAtom!==atom){throw def.error.operationInvalid("Atom is from a different root data.")}return atom}if(this.owner===this){throw def.error.operationInvalid("Atom is from a different root data.")}}dim_internAtom.call(this.parent||this.linkParent,atom);if(!this._lazyInit){this._atomsByKey[key]=atom;if(!key){this._nullAtom=atom;this._atoms.unshift(atom)}else{def.array.insert(this._atoms,atom,this._atomComparer)}dim_clearVisiblesCache.call(this)}return atom}function dim_buildDatumsFilterKey(keyArgs){var visible=def.get(keyArgs,'visible'),selected=def.get(keyArgs,'selected');return(visible==null?null:!!visible)+':'+(selected==null?null:!!selected)}function dim_createNullAtom(sourceValue){var nullAtom=this._nullAtom;if(!nullAtom){if(this.owner===this){var typeFormatter=this.type._formatter;var label=""+(typeFormatter?typeFormatter.call(null,null,sourceValue):"");nullAtom=new pvc.data.Atom(this,null,label,null,'');this.data._atomsBase[this.name]=nullAtom}else{nullAtom=dim_createNullAtom.call(this.parent||this.linkParent,sourceValue)}this._atomsByKey['']=this._nullAtom=nullAtom;this._atoms.unshift(nullAtom)}return nullAtom}function dim_createVirtualNullAtom(){(this.owner===this)||def.assert("Can only create atoms on an owner dimension.");if(!this._virtualNullAtom){this._virtualNullAtom=new pvc.data.Atom(this,null,"",null,'');this.data._atomsBase[this.name]=this._virtualNullAtom}return this._virtualNullAtom}function dim_unintern(atom){(this.owner===this)||def.assert("Can only unintern atoms on an owner dimension.");(atom&&atom.dimension===this)||def.assert("Not an interned atom");if(atom===this._virtualNullAtom){return}var key=atom.key;if(this._atomsByKey[key]===atom){def.array.remove(this._atoms,atom,this._atomComparer);delete this._atomsByKey[key];if(!key){delete this._nullAtom;this.data._atomsBase[this.name]=this._virtualNullAtom}}dim_clearVisiblesCache.call(this)}function dim_uninternUnvisitedAtoms(){(this.owner===this)||def.assert("Can only unintern atoms of an owner dimension.");var atoms=this._atoms;if(atoms){var atomsByKey=this._atomsByKey;var i=0;var L=atoms.length;while(i0))||def.assert("Must have had accounted for at least one visible datum.");map[key]=(count||0)+(visible?1:-1);this._visibleAtoms=this._sumCache=this._visibleIndexes=null}}function dim_getVisibleDatumsCountMap(){var map=this._atomVisibleDatumsCount;if(!map){map={};this.data.datums(null,{visible:true}).each(function(datum){var atom=datum.atoms[this.name],key=atom.key;map[key]=(map[key]||0)+1},this);this._atomVisibleDatumsCount=map}return map}function dim_calcVisibleIndexes(visible){var indexes=[];this._atoms.forEach(function(atom,index){if(this.isVisible(atom)===visible){indexes.push(index)}},this);return indexes}function dim_calcVisibleAtoms(visible){return def.query(this._atoms).where(function(atom){return this.isVisible(atom)===visible},this).array()} -def.type('pvc.data.Data',pvc.data.Complex).init(function(keyArgs){keyArgs||def.fail.argumentRequired('keyArgs');this._visibleDatums=new def.Map();var owner,atoms,atomsBase,dimNames,datums,index,parent=this.parent=keyArgs.parent||null;if(parent){this.root=parent.root;this.depth=parent.depth+1;this.type=parent.type;datums=keyArgs.datums||def.fail.argumentRequired('datums');owner=parent.owner;atoms=keyArgs.atoms||def.fail.argumentRequired('atoms');dimNames=keyArgs.dimNames||def.fail.argumentRequired('dimNames');atomsBase=parent.atoms}else{this.root=this;dimNames=[];var linkParent=keyArgs.linkParent||null;if(linkParent){owner=linkParent.owner;this.type=owner.type;datums=keyArgs.datums||def.fail.argumentRequired('datums');this._leafs=[];atomsBase=linkParent.atoms;index=def.get(keyArgs,'index',null);data_addLinkChild.call(linkParent,this,index)}else{owner=this;atomsBase={};if(keyArgs.labelSep){this.labelSep=keyArgs.labelSep}this.type=keyArgs.type||def.fail.argumentRequired('type');this._selectedDatums=new def.Map()}}if(datums){data_setDatums.call(this,datums)}this.owner=owner;this._atomsBase=atomsBase;this._dimensions={};this.type.dimensionsList().forEach(this._initDimension,this);this.base(owner,atoms,dimNames,atomsBase,true);pv.Dom.Node.call(this,null);delete this.nodeValue;this._children=this.childNodes;if(parent){index=def.get(keyArgs,'index',null);data_addChild.call(parent,this,index);if(parent.absLabel){this.absLabel=def.string.join(owner.labelSep,parent.absLabel,this.label)}else{this.absLabel=this.label}if(parent.absKey){this.absKey=def.string.join(",",parent.absKey,this.key)}else{this.absKey=this.key}}else{this.absLabel=this.label;this.absKey=this.key}}).add(pv.Dom.Node).add({parent:null,linkParent:null,_dimensions:null,_freeDimensionNames:null,_children:null,_linkChildren:null,_leafs:null,_childrenByKey:null,_visibleDatums:null,_selectedDatums:null,_groupByCache:null,_sumAbsCache:null,treeHeight:null,_groupOper:null,_groupSpec:null,_groupLevel:null,_datums:null,_datumsById:null,depth:0,label:"",absLabel:"",_disposed:false,_isFlattenGroup:false,_isDegenerateFlattenGroup:false,_initDimension:function(dimType){this._dimensions[dimType.name]=new pvc.data.Dimension(this,dimType)},dimensions:function(name,keyArgs){if(name==null){return this._dimensions}var dim=def.getOwn(this._dimensions,name);if(!dim&&def.get(keyArgs,'assertExists',true)){throw def.error.argumentInvalid('name',"Undefined dimension '{0}'.",[name])}return dim},freeDimensionNames:function(){if(!this._freeDimensionNames){var free=this._freeDimensionNames=[];def.eachOwn(this._dimensions,function(dim,dimName){var atom=this.atoms[dimName];if(!(atom instanceof pvc.data.Atom)||atom.value==null){free.push(dimName)}},this)}return this._freeDimensionNames},isOwner:function(){return this.owner===this},children:function(){if(!this._children){return def.query()}return def.query(this._children)},childCount:function(){return this._children?this._children.length:0},leafs:function(){return def.query(this._leafs)},count:function(){return this._datums.length},singleDatum:function(){var datums=this._datums;return datums.length===1?datums[0]:null},dispose:function(){if(!this._disposed){data_disposeChildLists.call(this);if(this._selectedDatums){this._selectedDatums.clear()}this._visibleDatums.clear();def.eachOwn(this._dimensions,function(dimension){dimension.dispose()});if(this.parent){this.parent.removeChild(this);this.parent=null}if(this.linkParent){data_removeLinkChild.call(this.linkParent,this)}this._disposed=true}},disposeChildren:function(){data_disposeChildLists.call(this)}});function data_addChild(child,index){this.insertAt(child,index);(this._childrenByKey||(this._childrenByKey={}))[child.key]=child}function data_addLinkChild(linkChild,index){data_addColChild(this,'_linkChildren',linkChild,'linkParent',index)}function data_removeLinkChild(linkChild){data_removeColChild(this,'_linkChildren',linkChild,'linkParent')}function data_disposeChildLists(){data_disposeChildList(this._children,'parent');this._childrenByKey=null;data_disposeChildList(this._linkChildren,'linkParent');this._groupByCache=null;this._sumAbsCache=null}function data_assertIsOwner(){this.isOwner()||def.fail("Can only be called on the owner data.")} -pvc.data.Data.add({selectedCount:function(){if(!this.isOwner()){return this.datums(null,{selected:true}).count()}return this._selectedDatums.count},selectedDatums:function(){if(!this.isOwner()){return this.datums(null,{selected:true}).array()}return this._selectedDatums.values()},selectedDatumMap:function(){if(!this.isOwner()){var datums=this.datums(null,{selected:true}).object({name:function(datum){return datum.id}});return new def.Set(datums)}return this._selectedDatums.clone()},visibleCount:function(){return this._visibleDatums.count},replaceSelected:function(datums){if(!def.array.is(datums)){datums=datums.array()}var alreadySelectedById=def.query(datums).where(function(datum){return datum.isSelected}).object({name:function(datum){return datum.id}});var changed=this.owner.clearSelected(function(datum){return!def.hasOwn(alreadySelectedById,datum.id)});changed|=pvc.data.Data.setSelected(datums,true);return changed},clearSelected:function(funFilter){if(this.owner!==this){return this.owner.clearSelected(funFilter)}if(!this._selectedDatums.count){return false}var changed;if(funFilter){changed=false;this._selectedDatums.values().filter(funFilter).forEach(function(datum){changed=true;datum_deselect.call(datum);this._selectedDatums.rem(datum.id)},this)}else{changed=true;this._selectedDatums.values().forEach(function(datum){datum_deselect.call(datum)});this._selectedDatums.clear()}return changed}});function data_onDatumSelectedChanged(datum,selected){!datum.isNull||def.assert("Null datums do not notify selected changes");if(selected){this._selectedDatums.set(datum.id,datum)}else{this._selectedDatums.rem(datum.id)}this._sumAbsCache=null}function data_onDatumVisibleChanged(datum,visible){if(def.hasOwn(this._datumsById,datum.id)){!datum.isNull||def.assert("Null datums do not notify visible changes");if(visible){this._visibleDatums.set(datum.id,datum)}else{this._visibleDatums.rem(datum.id)}this._sumAbsCache=null;def.eachOwn(this._dimensions,function(dimension){dim_onDatumVisibleChanged.call(dimension,datum,visible)});this._children.forEach(function(data){data_onDatumVisibleChanged.call(data,datum,visible)});if(this._linkChildren){this._linkChildren.forEach(function(data){data_onDatumVisibleChanged.call(data,datum,visible)})}}}pvc.data.Data.setSelected=function(datums,selected){var anyChanged=false;if(datums){def.query(datums).each(function(datum){if(datum.setSelected(selected)){anyChanged=true}})}return anyChanged};pvc.data.Data.toggleSelected=function(datums){if(!def.array.isLike(datums)){datums=def.query(datums).array()}var allSelected=def.query(datums).all(function(datum){return datum.isNull||datum.isSelected});return this.setSelected(datums,!allSelected)};pvc.data.Data.setVisible=function(datums,visible){var anyChanged=false;if(datums){def.query(datums).each(function(datum){if(datum.setVisible(visible)){anyChanged=true}})}return anyChanged};pvc.data.Data.toggleVisible=function(datums){if(!def.array.isLike(datums)){datums=def.query(datums).array()}var allVisible=def.query(datums).all(function(datum){return datum.isVisible});return pvc.data.Data.setVisible(datums,!allVisible)}; -def.type('pvc.data.GroupingSpec').init(function(levelSpecs,type,keyArgs){this.type=type||null;var ids=[];this.hasCompositeLevels=false;var dimNames=[];this.levels=def.query(levelSpecs||undefined).where(function(levelSpec){return levelSpec.dimensions.length>0}).select(function(levelSpec){ids.push(levelSpec.id);def.array.append(dimNames,levelSpec.dimensionNames());if(!this.hasCompositeLevels&&levelSpec.dimensions.length>1){this.hasCompositeLevels=true}levelSpec._setAccDimNames(dimNames.slice(0));return levelSpec},this).array();this._dimNames=dimNames;this.depth=this.levels.length;this.isSingleLevel=this.depth===1;this.isSingleDimension=this.isSingleLevel&&!this.hasCompositeLevels;this.firstDimension=this.depth>0?this.levels[0].dimensions[0]:null;this.flatteningMode=def.get(keyArgs,'flatteningMode')||null;this.flattenRootLabel=def.get(keyArgs,'flattenRootLabel')||'';this.id=(this.flatteningMode||'')+"##"+this.flattenRootLabel+"##"+ids.join('||')}).add({bind:function(type){this.type=type||def.fail.argumentRequired('type');this.levels.forEach(function(levelSpec){levelSpec.bind(type)})},dimensions:function(){return def.query(this.levels).selectMany(function(level){return level.dimensions})},dimensionNames:function(){return this._dimNames},view:function(complex){return complex.view(this.dimensionNames())},isDiscrete:function(){var d;return!this.isSingleDimension||(!!(d=this.firstDimension)&&d.type.isDiscrete)},firstDimensionType:function(){var d=this.firstDimension;return d&&d.type},firstDimensionName:function(){var dt=this.firstDimensionType();return dt&&dt.name},firstDimensionValueType:function(){var dt=this.firstDimensionType();return dt&&dt.valueType},isNull:function(){return!this.levels.length},ensure:function(keyArgs){var grouping=this,flatteningMode=def.get(keyArgs,'flatteningMode');if(flatteningMode){if(flatteningMode==='singleLevel'){return grouping.singleLevelGrouping(keyArgs)}var flattenRootLabel=def.get(keyArgs,'flattenRootLabel')||'';if(this.flatteningMode!==flatteningMode||(this.flattenRootLabel!==flattenRootLabel)){grouping=new pvc.data.GroupingSpec(grouping.levels,grouping.type,{flatteningMode:flatteningMode,flattenRootLabel:flattenRootLabel})}}if(def.get(keyArgs,'reverse',false)){grouping=grouping.reversed()}return grouping},singleLevelGrouping:function(keyArgs){var reverse=!!def.get(keyArgs,'reverse',false);if(this.isSingleLevel&&!reverse){return this}this._singleLevelGrouping||(this._singleLevelGrouping={});var singleLevel=this._singleLevelGrouping[reverse];if(!singleLevel){var dimSpecs=this.dimensions().select(function(dimSpec){return reverse?new pvc.data.GroupingDimensionSpec(dimSpec.name,!dimSpec.reverse,dimSpec.type.complexType):dimSpec});var levelSpec=new pvc.data.GroupingLevelSpec(dimSpecs,this.type);singleLevel=new pvc.data.GroupingSpec([levelSpec],this.type,{flatteningMode:this.flatteningMode});this._singleLevelGrouping[reverse]=singleLevel}return singleLevel},reversed:function(){var reverseGrouping=this._reverseGrouping;if(!reverseGrouping){var levelSpecs=def.query(this.levels).select(function(levelSpec){var dimSpecs=def.query(levelSpec.dimensions).select(function(dimSpec){return new pvc.data.GroupingDimensionSpec(dimSpec.name,!dimSpec.reverse,dimSpec.type.complexType)});return new pvc.data.GroupingLevelSpec(dimSpecs,this.type)});reverseGrouping=new pvc.data.GroupingSpec(levelSpecs,this.type,{flatteningMode:this.flatteningMode});this._reverseGrouping=reverseGrouping}return reverseGrouping},toString:function(){return def.query(this.levels).select(function(level){return''+level}).array().join(', ')}});def.type('pvc.data.GroupingLevelSpec').init(function(dimSpecs,type){var ids=[];var dimNames=[];this.dimensions=def.query(dimSpecs).select(function(dimSpec){ids.push(dimSpec.id);dimNames.push(dimSpec.name);return dimSpec}).array();this._dimNames=dimNames;this.dimensionsInDefOrder=this.dimensions.slice(0);if(type){this._sortDimensions(type)}this.id=ids.join(',');this.depth=this.dimensions.length;var me=this;this.comparer=function(a,b){return me.compare(a,b)}}).add({_sortDimensions:function(type){type.sortDimensionNames(this.dimensionsInDefOrder,function(d){return d.name})},_setAccDimNames:function(accDimNames){this._accDimNames=accDimNames},accDimensionNames:function(){return this._accDimNames},dimensionNames:function(){return this._dimNames},bind:function(type){this._sortDimensions(type);this.dimensions.forEach(function(dimSpec){dimSpec.bind(type)})},compare:function(a,b){for(var i=0,D=this.depth;i0){this._groupSpecRecursive(rootNode,datumsQuery,0)}return rootNode},_groupSpecRecursive:function(specParentNode,specDatumsQuery,specIndex){var groupSpec=this._groupSpecs[specIndex];var levelSpecs=groupSpec.levels;var L=levelSpecs.length;var doFlatten=!!groupSpec.flatteningMode;var nextSpecIndex=specIndex+1;var isLastSpec=(nextSpecIndex>=this._groupSpecs.length);var isPostOrder=doFlatten&&(groupSpec.flatteningMode==='tree-post');var specGroupParent;if(doFlatten){specParentNode.children=[];specParentNode.childrenByKey={};specGroupParent={key:'',absKey:'',atoms:{},datums:[],label:groupSpec.flattenRootLabel,dimNames:[]};if(!isPostOrder){specParentNode.children.push(specGroupParent);specParentNode.childrenByKey['']=specGroupParent}}else{specGroupParent=specParentNode}groupLevelRecursive.call(this,specGroupParent,specDatumsQuery,0);if(doFlatten){if(isPostOrder){specParentNode.children.push(specGroupParent)}specParentNode.datums=specGroupParent.datums}function groupLevelRecursive(levelParentNode,levelDatums,levelIndex){var levelSpec=levelSpecs[levelIndex];if(!doFlatten){levelParentNode.children=[];levelParentNode.groupSpec=groupSpec;levelParentNode.groupLevelSpec=levelSpec}var childNodes=this._groupDatums(levelSpec,levelParentNode,levelDatums,doFlatten);var isLastSpecLevel=levelIndex===L-1;var willRecurseParent=doFlatten&&!isLastSpec;var levelParentDatums=willRecurseParent?[]:levelParentNode.datums;childNodes.forEach(function(child){var childDatums=child.datums;if(!(isLastSpec&&isLastSpecLevel)){child.datums=[]}var specParentChildIndex;if(!doFlatten){levelParentNode.children.push(child)}else{def.array.lazy(levelParentNode,'_children').push(child);if(def.hasOwn(specParentNode.childrenByKey,child.key)){def.array.append(levelParentDatums,childDatums);return}specParentChildIndex=specParentNode.children.length;if(!isPostOrder){specParentNode.children.push(child);specParentNode.childrenByKey[child.key]=child;levelParentNode.isFlattenGroup=true}}if(!isLastSpecLevel){groupLevelRecursive.call(this,child,childDatums,levelIndex+1)}else if(!isLastSpec){this._groupSpecRecursive(child,childDatums,nextSpecIndex)}def.array.append(levelParentDatums,child.datums);if(doFlatten&&isPostOrder){if(def.hasOwn(specParentNode.childrenByKey,child.key)){child.isFlattenGroup||def.assert("Must be a parent for duplicate keys to exist.");if(child._children.length===1){specParentNode.children.splice(specParentChildIndex,specParentNode.children.length-specParentChildIndex);child.isDegenerateFlattenGroup=true}}specParentNode.children.push(child);specParentNode.childrenByKey[child.key]=child;levelParentNode.isFlattenGroup=true}},this);if(willRecurseParent){this._groupSpecRecursive(levelParentNode,levelParentDatums,nextSpecIndex)}}},_groupDatums:function(levelSpec,levelParentNode,levelDatums,doFlatten){var firstDatums=[];var childNodes=new def.OrderedMap();def.query(levelDatums).each(function(datum){var newChild=levelSpec.key(datum);var key=newChild.key;var child=childNodes.get(key);if(child){child.datums.push(datum)}else{child=newChild;child.datums=[datum];if(doFlatten){def.copy(child.atoms,levelParentNode.atoms);if(levelParentNode.dimNames.length){var keySep=datum.owner.keySep;child.absKey=levelParentNode.absKey+keySep+key;var K=keySep.length;var trimKey=child.absKey;while(trimKey.lastIndexOf(keySep)===trimKey.length-K){trimKey=trimKey.substr(0,trimKey.length-K)}child.key=trimKey}else{child.absKey=key}child.dimNames=levelSpec.accDimensionNames()}var datumIndex=def.array.insert(firstDatums,datum,levelSpec.comparer);childNodes.add(key,child,~datumIndex)}});return childNodes},_generateData:function(node,parentNode,parentData,rootData){var data,isNew;if(node.isRoot){if(rootData){data=rootData;data_addDatumsLocal.call(data,node.datums)}else{isNew=true;data=new pvc.data.Data({linkParent:parentData,datums:node.datums});data.treeHeight=node.treeHeight;data._groupOper=this}}else{if(rootData){data=def.get(parentData._childrenByKey,node.key);if(data){data_addDatumsSimple.call(data,node.datums)}}if(!data){isNew=true;var index,siblings;if(rootData&&(siblings=parentData._children)){index=~def.array.binarySearch(siblings,node.datums[0],parentNode.groupLevelSpec.comparer)}data=new pvc.data.Data({parent:parentData,atoms:node.atoms,dimNames:node.dimNames,datums:node.datums,index:index})}}if(isNew&&node.isFlattenGroup){data._isFlattenGroup=true;data._isDegenerateFlattenGroup=!!node.isDegenerateFlattenGroup;var label=node.label;if(label){data.label+=label;data.absLabel+=label}}var childNodes=node.children;if(childNodes&&childNodes.length){if(isNew){data._groupSpec=node.groupSpec;data._groupLevelSpec=node.groupLevelSpec}childNodes.forEach(function(childNode){this._generateData(childNode,node,data,rootData)},this)}else if(isNew&&!node.isRoot){var leafs=data.root._leafs;data.leafIndex=leafs.length;leafs.push(data)}return data}}); -def.type('pvc.data.LinearInterpolationOper').init(function(allPartsData,data,catRole,serRole,valRole,stretchEnds){this._newDatums=[];this._data=data;var allCatDataRoot=allPartsData.flattenBy(catRole,{ignoreNulls:false});var allCatDatas=allCatDataRoot._children;var serDatas1=this._serDatas1=serRole.isBound()?data.flattenBy(serRole).children().array():[null];this._isCatDiscrete=catRole.grouping.isDiscrete();this._firstCatDim=!this._isCatDiscrete?data.owner.dimensions(catRole.firstDimensionName()):null;this._stretchEnds=stretchEnds;var valDim=this._valDim=data.owner.dimensions(valRole.firstDimensionName());var visibleKeyArgs={visible:true,zeroIfNone:false};this._catInfos=allCatDatas.map(function(allCatData,catIndex){var catData=data._childrenByKey[allCatData.key];var catInfo={data:catData||allCatData,value:allCatData.value,isInterpolated:false,serInfos:null,index:catIndex};catInfo.serInfos=serDatas1.map(function(serData1){var group=catData;if(group&&serData1){group=group._childrenByKey[serData1.key]}var value=group?group.dimensions(valDim.name).sum(visibleKeyArgs):null;return{data:serData1,group:group,value:value,isNull:value==null,catInfo:catInfo}},this);return catInfo});this._serCount=serDatas1.length;this._serStates=def.range(0,this._serCount).select(function(serIndex){return new pvc.data.LinearInterpolationOperSeriesState(this,serIndex)},this).array()}).add({interpolate:function(){var catInfo;while((catInfo=this._catInfos.shift())){catInfo.serInfos.forEach(this._visitSeries,this)}var newDatums=this._newDatums;if(newDatums.length){this._data.owner.add(newDatums)}},_visitSeries:function(catSerInfo,serIndex){this._serStates[serIndex].visit(catSerInfo)},nextUnprocessedNonNullCategOfSeries:function(serIndex){var catIndex=0,catCount=this._catInfos.length;while(catIndex=2)||def.assert("Must have at least one interpolation point.");this._stepValue=deltaValue/stepCount;this._middleIndex=~~(stepCount/2); var dotCount=(stepCount-1);this._isOdd=(dotCount%2)>0}else{var fromCat=+last.catInfo.value;var toCat=+next.catInfo.value;var deltaCat=toCat-fromCat;this._steep=deltaValue/deltaCat; this._middleCat=(toCat+fromCat)/2}}},_interpolate:function(catSerInfo){this._initInterpData();var next=this.__nextNonNull;var last=this.__lastNonNull;var one=next||last;if(!one){return}var value,group;var interpolation=this.interpolation;var catInfo=catSerInfo.catInfo;if(next&&last){if(interpolation._isCatDiscrete){var groupIndex=(catInfo.index-last.catInfo.index);value=last.value+this._stepValue*groupIndex;if(this._isOdd){group=groupIndex=2)||def.assert("Must have at least one interpolation point.");this._middleIndex=~~(stepCount/2); var dotCount=(stepCount-1);this._isOdd=(dotCount%2)>0}else{var fromCat=+last.catInfo.value;var toCat=+next.catInfo.value;this._middleCat=(toCat+fromCat)/2}}},_interpolate:function(catSerInfo){this._initInterpData();var next=this.__nextNonNull;var last=this.__lastNonNull;var one=next||last;if(!one){return}var group;var interpolation=this.interpolation;var catInfo=catSerInfo.catInfo;if(next&&last){if(interpolation._isCatDiscrete){var groupIndex=(catInfo.index-last.catInfo.index);if(this._isOdd){group=groupIndex=7){pvc.log("[GroupBy] "+(cacheKey?("Cache key not found: '"+cacheKey+"'"):"No Cache key"))}data=groupOper.execute();if(cacheKey){(groupByCache||(this._groupByCache={}))[cacheKey]=data}}else if(pvc.debug>=7){pvc.log("[GroupBy] Cache key hit '"+cacheKey+"'")}return data},flattenBy:function(role,keyArgs){var grouping=role.flattenedGrouping(keyArgs)||def.fail.operationInvalid("Role is unbound.");return this.groupBy(grouping,keyArgs)},where:function(whereSpec,keyArgs){var datums=this.datums(whereSpec,keyArgs);return new pvc.data.Data({linkParent:this,datums:datums})},datums:function(whereSpec,keyArgs){if(!whereSpec){if(!keyArgs){return def.query(this._datums)}return data_whereState(def.query(this._datums),keyArgs)}whereSpec=data_processWhereSpec.call(this,whereSpec,keyArgs);return data_where.call(this,whereSpec,keyArgs)},datum:function(whereSpec,keyArgs){whereSpec||def.fail.argumentRequired('whereSpec');whereSpec=data_processWhereSpec.call(this,whereSpec,keyArgs);var datum=data_where.call(this,whereSpec,keyArgs).first()||null;if(!datum&&def.get(keyArgs,'createNull')&&whereSpec.length){var sourceDatumFilter=whereSpec[0],atoms={};for(var dimName in this._dimensions){var dimAtoms=sourceDatumFilter[dimName];if(dimAtoms){atoms[dimName]=dimAtoms[0]}}datum=new pvc.data.Datum(this,atoms,true)}return datum},firstDatum:function(){return this._datums.length?this._datums[0]:null},dimensionsSumAbs:function(dimName,keyArgs){var key=dimName+":"+dim_buildDatumsFilterKey(keyArgs),sum=def.getOwn(this._sumAbsCache,key);if(sum==null){sum=this.children().where(function(childData){return!childData._isFlattenGroup||childData._isDegenerateFlattenGroup}).select(function(childData){return Math.abs(childData.dimensions(dimName).sum(keyArgs))},this).reduce(def.add,0);(this._sumAbsCache||(this._sumAbsCache={}))[key]=sum}return sum}});function data_setDatums(newDatums,keyArgs){newDatums||def.fail.argumentRequired('newDatums');var doAtomGC=def.get(keyArgs,'doAtomGC',false);var isAdditive=def.get(keyArgs,'isAdditive',false);var visibleDatums=this._visibleDatums;var selectedDatums=this._selectedDatums;var newDatumsByKey={};var prevDatumsByKey;var prevDatums=this._datums;if(prevDatums){var processPrevAtoms=isAdditive&&doAtomGC;prevDatumsByKey=def.query(prevDatums).uniqueIndex(function(datum){if(processPrevAtoms){data_processDatumAtoms.call(this,datum,false,true)}return datum.key},this);if(isAdditive){this._sumAbsCache=null}else{data_disposeChildLists.call(this);if(selectedDatums){selectedDatums.clear()}visibleDatums.clear()}}else{isAdditive=false}var datumsById;if(isAdditive){datumsById=this._datumsById}else{datumsById=this._datumsById={}}if(def.array.is(newDatums)){var i=0;var L=newDatums.length;while(i=0){throw def.error.argumentInvalid('keyArgs.orderBy',"Multi-dimension order by is not supported.")}}var rootData=this.groupBy(groupingSpecText,keyArgs),H=rootData.treeHeight;var stateStack=[];return def.query(function(){var state;if(!this._data){this._data=rootData;this._dimAtomsOrQuery=def.query(datumFilter[rootData._groupLevelSpec.dimensions[0].name])}else if(this._datumsQuery){this._data||def.assert("Must have a current data");stateStack.length||def.assert("Must have a parent data");!this._dimAtomsOrQuery||def.assert();if(this._datumsQuery.next()){this.item=this._datumsQuery.item;return 1}this._datumsQuery=null;state=stateStack.pop();this._data=state.data;this._dimAtomsOrQuery=state.dimAtomsOrQuery}this._dimAtomsOrQuery||def.assert("Invalid programmer");this._data||def.assert("Must have a current data");var depth=stateStack.length;do{while(this._dimAtomsOrQuery.next()){var dimAtomOr=this._dimAtomsOrQuery.item,childData=this._data._childrenByKey[dimAtomOr.key];if(childData&&(depth10?"...":""))});return out.join("\n")},getValues:function(){return pv.range(0,this.getCategoriesSize()).map(function(categIndex){return this._getValuesForCategoryIndex(categIndex)},this)},_getDimensionValues:function(name){return this.dimensions(name).atoms().map(function(atom){return atom.value})},_getDimensionVisibleValues:function(name){return this.dimensions(name).atoms({visible:true}).map(function(atom){return atom.value})},getSeries:function(){return this._getDimensionValues('series')},getVisibleSeriesIndexes:function(){return this.dimensions('series').indexes({visible:true})},getVisibleCategoriesIndexes:function(){return this.dimensions('category').indexes({visible:true})},getVisibleSeries:function(){return this._getDimensionVisibleValues('series')},getCategories:function(){return this._getDimensionValues('category')},getVisibleCategories:function(){return this._getDimensionVisibleValues('category')},_getValuesForCategoryIndex:function(categIdx){var categAtom=this.dimensions('category').atoms()[categIdx];var datumsBySeriesKey=this.datums({category:categAtom}).uniqueIndex(function(datum){return datum.atoms.series.key});return this.dimensions('series').atoms().map(function(atom){var datum=def.getOwn(datumsBySeriesKey,atom.key);return datum?datum.atoms.value.value:null})},getSeriesSize:function(){var dim=this.dimensions('series',{assertExists:false});return dim?dim.count():0},getCategoriesSize:function(){var dim=this.dimensions('category',{assertExists:false});return dim?dim.count():0}}); -def.type('pvc.visual.Role').init(function(name,keyArgs){this.name=name;this.label=def.get(keyArgs,'label')||pvc.buildTitleFromName(name);this.index=def.get(keyArgs,'index')||0;this.dimensionDefaults=def.get(keyArgs,'dimensionDefaults')||{};if(def.get(keyArgs,'isRequired',false)){this.isRequired=true}if(def.get(keyArgs,'autoCreateDimension',false)){this.autoCreateDimension=true}var defaultSourceRoleName=def.get(keyArgs,'defaultSourceRole');if(defaultSourceRoleName){this.defaultSourceRoleName=defaultSourceRoleName}var defaultDimensionName=def.get(keyArgs,'defaultDimension');if(defaultDimensionName){this.defaultDimensionName=defaultDimensionName}if(!defaultDimensionName&&this.autoCreateDimension){throw def.error.argumentRequired('defaultDimension')}var requireSingleDimension;var requireIsDiscrete=def.get(keyArgs,'requireIsDiscrete');if(requireIsDiscrete!=null){if(!requireIsDiscrete){requireSingleDimension=true}}if(requireSingleDimension!=null){requireSingleDimension=def.get(keyArgs,'requireSingleDimension',false);if(requireSingleDimension){if(def.get(keyArgs,'isMeasure',false)){this.isMeasure=true;if(def.get(keyArgs,'isPercent',false)){this.isPercent=true}}var valueType=def.get(keyArgs,'valueType',null);if(valueType!==this.valueType){this.valueType=valueType;this.dimensionDefaults.valueType=valueType}}}if(requireSingleDimension!==this.requireSingleDimension){this.requireSingleDimension=requireSingleDimension}if(requireIsDiscrete!=this.requireIsDiscrete){this.requireIsDiscrete=!!requireIsDiscrete;this.dimensionDefaults.isDiscrete=this.requireIsDiscrete}var flatteningMode=def.get(keyArgs,'flatteningMode');if(flatteningMode&&flatteningMode!=this.flatteningMode){this.flatteningMode=flatteningMode}}).add({isRequired:false,requireSingleDimension:false,valueType:null,requireIsDiscrete:null,isMeasure:false,isPercent:false,defaultSourceRoleName:null,defaultDimensionName:null,grouping:null,flatteningMode:'singleLevel',flattenRootLabel:'',autoCreateDimension:false,isReversed:false,label:null,sourceRole:null,firstDimensionType:function(){var g=this.grouping;return g&&g.firstDimensionType()},firstDimensionName:function(){var g=this.grouping;return g&&g.firstDimensionName()},firstDimensionValueType:function(){var g=this.grouping;return g&&g.firstDimensionValueType()},isDiscrete:function(){var g=this.grouping;return g&&g.isDiscrete()},setSourceRole:function(sourceRole){this.sourceRole=sourceRole},setIsReversed:function(isReversed){if(!isReversed){delete this.isReversed}else{this.isReversed=true}},setFlatteningMode:function(flatteningMode){if(!flatteningMode||flatteningMode==='singleLevel'){delete this.flatteningMode}else{this.flatteningMode=flatteningMode}},setFlattenRootLabel:function(flattenRootLabel){if(!flattenRootLabel){delete this.flattenRootLabel}else{this.flattenRootLabel=flattenRootLabel}},flatten:function(data,keyArgs){if(this.grouping){return data.flattenBy(this,keyArgs)}},flattenedGrouping:function(keyArgs){var grouping=this.grouping;if(grouping){keyArgs=def.setDefaults(keyArgs,'flatteningMode',this.flatteningMode,'flattenRootLabel',this.flattenRootLabel);return grouping.ensure(keyArgs)}},select:function(data,keyArgs){var grouping=this.grouping;if(grouping){return data.groupBy(grouping.ensure(keyArgs),keyArgs)}},view:function(complex){var grouping=this.grouping;if(grouping){return grouping.view(complex)}},preBind:function(groupingSpec){this.__grouping=groupingSpec;return this},isPreBound:function(){return!!this.__grouping},preBoundGrouping:function(){return this.__grouping},isBound:function(){return!!this.grouping},postBind:function(type){var grouping=this.__grouping;if(grouping){delete this.__grouping;grouping.bind(type);this.bind(grouping)}return this},bind:function(groupingSpec){if(groupingSpec){if(groupingSpec.isNull()){groupingSpec=null}else{if(this.requireSingleDimension&&!groupingSpec.isSingleDimension){throw def.error.operationInvalid("Role '{0}' only accepts a single dimension.",[this.name])}var valueType=this.valueType;var requireIsDiscrete=this.requireIsDiscrete;groupingSpec.dimensions().each(function(dimSpec){var dimType=dimSpec.type;if(valueType&&dimType.valueType!==valueType){throw def.error.operationInvalid("Role '{0}' cannot be bound to dimension '{1}'. \nIt only accepts dimensions of type '{2}' and not of type '{3}'.",[this.name,dimType.name,pvc.data.DimensionType.valueTypeName(valueType),dimType.valueTypeName])}if(requireIsDiscrete!=null&&dimType.isDiscrete!==requireIsDiscrete){if(requireIsDiscrete){dimType._toDiscrete()}else{throw def.error.operationInvalid("Role '{0}' cannot be bound to dimension '{1}'. \nIt only accepts {2} dimensions.",[this.name,dimType.name,requireIsDiscrete?'discrete':'continuous'])}}},this)}}if(this.grouping){this.grouping.dimensions().each(function(dimSpec){if(dimSpec.type){dimType_removeVisualRole.call(dimSpec.type,this)}},this)}this.grouping=groupingSpec;if(this.grouping){if(this.isReversed){this.grouping=this.grouping.reversed()}this.grouping.dimensions().each(function(dimSpec){dimType_addVisualRole.call(dimSpec.type,this)},this)}return this}}); -def.type('pvc.visual.Scene').init(function(parent,keyArgs){if(pvc.debug>=4){this.id=def.nextId('scene')}this._renderId=0;this.renderState={};pv.Dom.Node.call(this,null);this.parent=parent||null;this.root=this;if(parent){var index=def.get(keyArgs,'index',null);parent.insertAt(this,index);this.root=parent.root}else{this._active=null;this._panel=def.get(keyArgs,'panel')||def.fail.argumentRequired('panel',"Argument is required on root scene.")}var group=def.get(keyArgs,'group',null),datum;if(group){datum=group._datums[0]}else{datum=def.get(keyArgs,'datum')}this.datum=datum||null;this.group=group;var parentAtoms;var source=(group||datum);this.atoms=source?source.atoms:(parentAtoms=(parent&&parent.atoms))?Object.create(parentAtoms):{};source=(datum||group);this.firstAtoms=source?source.atoms:(parentAtoms=(parent&&parent.firstAtoms))?Object.create(parentAtoms):this.atoms;if(!source){this.isNull=true}this.vars=parent?Object.create(parent.vars):{}}).add(pv.Dom.Node).add({isNull:false,datums:function(){return this.group?this.group.datums():(this.datum?def.query(this.datum):def.query())},format:function(mask){return def.format(mask,this._formatScope,this)},_formatScope:function(prop){if(prop.charAt(0)==='#'){prop=prop.substr(1).split('.');if(prop.length>2){throw def.error.operationInvalid("Scene format mask is invalid.")}var atom=this.atoms[prop[0]];if(atom){if(prop.length>1){switch(prop[1]){case'value':return atom.value;case'label':break;default:throw def.error.operationInvalid("Scene format mask is invalid.")}}return atom}return null}return def.getPath(this.vars,prop)},isRoot:function(){return this.root===this},panel:function(){return this.root._panel},chart:function(){return this.root._panel.chart},compatVersion:function(){return this.root._panel.compatVersion()},children:function(){if(!this.childNodes){return def.query()}return def.query(this.childNodes)},leafs:function(){function getFirstLeafFrom(leaf){while(leaf.childNodes.length){leaf=leaf.childNodes[0]}return leaf}var root=this;return def.query(function(nextIndex){if(!nextIndex){var item=getFirstLeafFrom(root);if(item===root){return 0}this.item=item;return 1}var next=this.item.nextSibling;if(next){this.item=next;return 1}var current=this.item;while((current!==root)&&(current=current.parentNode)){if((next=current.nextSibling)){this.item=getFirstLeafFrom(next);return 1}}return 0})},anyInteraction:function(){return(!!this.root._active||this.anySelected())},isActive:false,setActive:function(isActive){isActive=!!isActive;if(this.isActive!==isActive){rootScene_setActive.call(this.root,this.isActive?null:this)}},clearActive:function(){return rootScene_setActive.call(this.root,null)},anyActive:function(){return!!this.root._active},active:function(){return this.root._active},activeSeries:function(){var active=this.active();var seriesVar;return active&&(seriesVar=active.vars.series)&&seriesVar.value},isActiveSeries:function(){if(this.isActive){return true}var activeSeries;return(activeSeries=this.activeSeries())!=null&&(activeSeries===this.vars.series.value)},isSelected:function(){return this._selectedData().is},anySelected:function(){return this._selectedData().any},_selectedData:function(){return this.renderState._selectedData||(this.renderState._selectedData=this._createSelectedData())},_createSelectedData:function(){var any=this.panel().chart.data.owner.selectedCount()>0,isSelected=any&&this.datums().any(function(datum){return datum.isSelected});return{any:any,is:isSelected}}});function scene_renderId(renderId){if(this._renderId!==renderId){if(pvc.debug>=20){pvc.log({sceneId:this.id,oldRenderId:this._renderId,newRenderId:renderId})}this._renderId=renderId;this.renderState={}}}function rootScene_setActive(scene){var ownerScene;if(scene&&(ownerScene=scene.ownerScene)){scene=ownerScene}if(this._active!==scene){if(this._active){scene_setActive.call(this._active,false)}this._active=scene||null;if(this._active){scene_setActive.call(this._active,true)}return true}return false}function scene_setActive(isActive){isActive=!!isActive;if(this.isActive!==isActive){if(!isActive){delete this.isActive}else{this.isActive=true}}} -pvc.visual.ValueLabelVar=function(value,label,rawValue){this.value=value;this.label=label;if(rawValue!==undefined){this.rawValue=rawValue}};def.set(pvc.visual.ValueLabelVar.prototype,'rawValue',undefined,'clone',function(){return new pvc.visual.ValueLabelVar(this.value,this.label,this.rawValue)},'toString',function(){var label=this.label||this.value;return typeof label!=='string'?(''+label):label});pvc.visual.ValueLabelVar.fromComplex=function(complex){return complex?new pvc.visual.ValueLabelVar(complex.value,complex.label,complex.rawValue):new pvc.visual.ValueLabelVar(null,"",null)};def.type('pvc.visual.RoleVarHelper').init(function(rootScene,role,keyArgs){var g;var hasPercentSubVar=def.get(keyArgs,'hasPercentSubVar',false);if(!def.get(keyArgs,'forceUnbound',false)){this.role=role;this.sourceRoleName=role.sourceRole&&role.sourceRole.name;g=this.grouping=role.grouping;if(g&&!g.isDiscrete()){var panel=rootScene.panel();this.rootContDim=panel.data.owner.dimensions(g.firstDimensionName());if(hasPercentSubVar){this.percentFormatter=panel.chart.options.percentValueFormat}}}if(!g){var roleVar=rootScene.vars[role.name]=new pvc.visual.ValueLabelVar(null,"");if(hasPercentSubVar){roleVar.percent=new pvc.visual.ValueLabelVar(null,"")}}}).add({isBound:function(){return!!this.grouping},onNewScene:function(scene,isLeaf){if(!this.grouping){return}var roleName=this.role.name;if(scene.vars[roleName]){return}var sourceName=this.sourceRoleName;if(sourceName){var sourceVar=def.getOwn(scene.vars,sourceName);if(sourceVar){scene.vars[roleName]=sourceVar.clone();return}}if(isLeaf){var roleVar;var rootContDim=this.rootContDim;if(!rootContDim){var firstDatum=scene.datum;if(firstDatum&&!firstDatum.isNull){var view=this.grouping.view(firstDatum);roleVar=new pvc.visual.ValueLabelVar(view.value,view.label,view.rawValue)}}else{var group=scene.group;var singleDatum=group?group.singleDatum():scene.datum;if(singleDatum){if(!singleDatum.isNull){roleVar=Object.create(singleDatum.atoms[rootContDim.name])}}else if(group){var valueDim=group.dimensions(rootContDim.name);var value=valueDim.sum({visible:true,zeroIfNone:false});var label=rootContDim.format(value);roleVar=new pvc.visual.ValueLabelVar(value,label,value);if(this.percentFormatter){if(value==null){roleVar.percent=new pvc.visual.ValueLabelVar(value,label)}else{var valuePct=valueDim.percentOverParent({visible:true});roleVar.percent=new pvc.visual.ValueLabelVar(valuePct,this.percentFormatter.call(null,valuePct))}}}}scene.vars[roleName]=roleVar||new pvc.visual.ValueLabelVar(null,"")}}}); -(function(){pv.Mark.prototype.getSign=function(){return this.sign||createBasic(this)};pv.Mark.prototype.getScene=function(){return this.getSign().scene};function createBasic(pvMark){var as=getAncestorSign(pvMark)||def.assert("There must exist an ancestor sign");var bs=new pvc.visual.BasicSign(as.panel,pvMark);var i;var s=pvMark.scene;if(s&&(i=pvMark.index)!=null&&i>=0){bs._buildInstance(pvMark,s[i],true)}return bs}function getAncestorSign(pvMark){var sign;do{pvMark=pvMark.parent}while(pvMark&&!(sign=pvMark.sign)&&(!pvMark.proto||!(sign=pvMark.proto.sign)));return sign}def.type('pvc.visual.BasicSign').init(function(panel,pvMark){this.chart=panel.chart;this.panel=panel;this.pvMark=pvMark;!pvMark.sign||def.assert("Mark already has an attached Sign.");pvMark.sign=this;pvMark.__buildInstance=pvMark.buildInstance;pvMark.buildInstance=this._dispatchBuildInstance}).add({localProperty:function(name,type){this.pvMark.localProperty(name,type);return this},lock:function(name,value){return this.lockMark(name,this._bindWhenFun(value))},optional:function(name,value,tag){return this.optionalMark(name,this._bindWhenFun(value),tag)},lockMark:function(name,value){this.pvMark.lock(name,value);return this},optionalMark:function(name,value,tag){this.pvMark[name](value,tag);return this},delegate:function(dv,tag){return this.pvMark.delegate(dv,tag)},delegateExtension:function(dv){return this.pvMark.delegate(dv,pvc.extensionTag)},hasDelegate:function(tag){return this.pvMark.hasDelegate(tag)},_bindWhenFun:function(value){if(typeof value==='function'){return function(){var sign=this.getSign();return value.apply(sign,arguments)}}return value},_lockDynamic:function(name,method){var me=this;return this.lockMark(name,function(){var sign=this.getSign();var m=sign[method]||me[method]||def.assert("No method with name '"+method+"' is defined");return m.apply(sign,arguments)})},_dispatchBuildInstance:function(instance){this.sign._buildInstance(this,instance)},_buildInstance:function(mark,instance,lateCall){var scene=instance.data;var index=scene?scene.childIndex():0;this.pvInstance=instance;this.scene=scene;this.index=index<0?0:index;scene_renderId.call(scene,mark.renderId());this.state={};if(!lateCall){mark.__buildInstance.call(mark,instance)}}})}()); -def.type('pvc.visual.Sign',pvc.visual.BasicSign).init(function(panel,pvMark,keyArgs){this.base(panel,pvMark,keyArgs);this.bits=0;var extensionIds=def.get(keyArgs,'extensionId');if(extensionIds!=null){this.extensionAbsIds=def.array.to(panel._makeExtensionAbsId(extensionIds))}this.isActiveSeriesAware=def.get(keyArgs,'activeSeriesAware',true)&&!!this.chart.visualRoles('series',{assertExists:false});var wrapper=def.get(keyArgs,'wrapper');if(!wrapper){wrapper=function(f){return function(scene){return f.call(panel._getContext(pvMark),scene)}}}pvMark.wrapper(wrapper);if(!def.get(keyArgs,'freeColor',true)){this._bindProperty('fillStyle','fillColor','color')._bindProperty('strokeStyle','strokeColor','color')}}).postInit(function(panel,pvMark,keyArgs){panel._addSign(this);this._addInteractive(keyArgs)}).add({property:function(name){var upperName=def.firstUpperCase(name);var baseName='base'+upperName;var defName='default'+upperName;var normalName='normal'+upperName;var interName='interactive'+upperName;var methods={};methods[name]=function(arg){delete this._finished;var value;this._arg=arg;try{value=this[baseName](arg);if(value==null){return null}if(this.hasOwnProperty('_finished')){return value}if(this.showsInteraction()&&this.scene.anyInteraction()){value=this[interName](value,arg)}else{value=this[normalName](value,arg)}}finally{delete this._arg}return value};methods[baseName]=function(arg){return this.delegateExtension()};methods[defName]=function(arg){return};methods[normalName]=function(value,arg){return value};methods[interName]=function(value,arg){return value};this.constructor.add(methods);return this},finished:function(value){this._finished=true;return value},applyExtensions:function(){if(!this._extended){this._extended=true;var extensionAbsIds=this.extensionAbsIds;if(extensionAbsIds){extensionAbsIds.forEach(function(extensionAbsId){this.panel.extendAbs(this.pvMark,extensionAbsId)},this)}}return this},intercept:function(name,fun){return this._intercept(name,fun.bind(this))},lockDimensions:function(){this.pvMark.lock('left').lock('right').lock('top').lock('bottom').lock('width').lock('height');return this},_extensionKeyArgs:{tag:pvc.extensionTag},_bindProperty:function(pvName,prop,realProp){var me=this;if(!realProp){realProp=prop}var defaultPropName="default"+def.firstUpperCase(realProp);if(def.fun.is(this[defaultPropName])){if(!this.pvMark.hasDelegateValue(pvName,pvc.extensionTag)){var defaultMethodCaller=function(){return me[defaultPropName](me._arg)};this.pvMark.intercept(pvName,defaultMethodCaller,this._extensionKeyArgs)}}function mainMethodCaller(){return me[prop]()}return this._intercept(pvName,mainMethodCaller)},_intercept:function(name,fun){var mark=this.pvMark;var extensionAbsIds=this.extensionAbsIds;if(extensionAbsIds){def.query(extensionAbsIds).select(function(extensionAbsId){return this.panel._getExtensionAbs(extensionAbsId,name)},this).where(def.notUndef).each(function(extValue){extValue=mark.wrap(extValue,name);mark.intercept(name,extValue,this._extensionKeyArgs)},this)}(mark._intercepted||(mark._intercepted={}))[name]=true;mark.intercept(name,fun);return this}}).prototype.property('color').constructor.add({_bitShowsActivity:2,_bitShowsSelection:4,_bitShowsInteraction:4|2,_bitShowsTooltip:8,_bitSelectable:16,_bitHoverable:32,_bitClickable:64,_bitDoubleClickable:128,showsInteraction:function(){return(this.bits&this._bitShowsInteraction)!==0},showsActivity:function(){return(this.bits&this._bitShowsActivity)!==0},showsSelection:function(){return(this.bits&this._bitShowsSelection)!==0},showsTooltip:function(){return(this.bits&this._bitShowsTooltip)!==0},isSelectable:function(){return(this.bits&this._bitSelectable)!==0},isHoverable:function(){return(this.bits&this._bitHoverable)!==0},isClickable:function(){return(this.bits&this._bitClickable)!==0},isDoubleClickable:function(){return(this.bits&this._bitDoubleClickable)!==0},extensionAbsIds:null,_addInteractive:function(keyArgs){var panel=this.panel,pvMark=this.pvMark,chart=this.chart,options=chart.options;var bits=this.bits;bits|=this._bitShowsInteraction;if(chart._tooltipEnabled&&!def.get(keyArgs,'noTooltip')){bits|=this._bitShowsTooltip;this.panel._addPropTooltip(pvMark,def.get(keyArgs,'tooltipArgs'))}var clickSelectable=false;var clickable=false;if(options.selectable||options.hoverable){if(options.selectable&&!def.get(keyArgs,'noSelect')){bits|=this._bitSelectable;clickSelectable=!def.get(keyArgs,'noClickSelect')&&chart._canSelectWithClick()}if(options.hoverable&&!def.get(keyArgs,'noHover')){bits|=this._bitHoverable;panel._addPropHoverable(pvMark)}}var showsInteraction=def.get(keyArgs,'showsInteraction');if(showsInteraction!=null){if(showsInteraction){bits|=this._bitShowsInteraction}else{bits&=~this._bitShowsInteraction}}var showsActivity=def.get(keyArgs,'showsActivity');if(showsActivity!=null){if(showsActivity){bits|=this._bitShowsActivity}else{bits&=~this._bitShowsActivity}}var showsSelection=def.get(keyArgs,'showsSelection');if(showsSelection!=null){if(showsSelection){bits|=this._bitShowsSelection}else{bits&=~this._bitShowsSelection}}if(!def.get(keyArgs,'noClick')&&panel._isClickable()){bits|=this._bitClickable;clickable=true}if(clickSelectable||clickable){panel._addPropClick(pvMark)}if(!def.get(keyArgs,'noDoubleClick')&&panel._isDoubleClickable()){bits|=this._bitDoubleClickable;panel._addPropDoubleClick(pvMark)}this.bits=bits},fillColor:function(){return this.color('fill')},strokeColor:function(){return this.color('stroke')},defaultColor:function(){return this.defaultColorSceneScale()(this.scene)},dimColor:function(color){return pvc.toGrayScale(color,-0.3,null,null)},_initDefaultColorSceneScale:function(){var colorAxis=this.panel.axes.color;return colorAxis?colorAxis.sceneScale({nullToZero:false}):def.fun.constant(pvc.defaultColor)},defaultColorSceneScale:function(){return this._defaultColorSceneScale||(this._defaultColorSceneScale=this._initDefaultColorSceneScale())}}); -def.type('pvc.visual.Panel',pvc.visual.Sign).init(function(panel,protoMark,keyArgs){var pvPanel=def.get(keyArgs,'panel');if(!pvPanel){var pvPanelType=def.get(keyArgs,'panelType')||pv.Panel;pvPanel=protoMark.add(pvPanelType)}this.base(panel,pvPanel,keyArgs)}).add({_addInteractive:function(keyArgs){var t=true;keyArgs=def.setDefaults(keyArgs,'noSelect',t,'noHover',t,'noTooltip',t,'noClick',t,'noDoubleClick',t);this.base(keyArgs)}}); -def.type('pvc.visual.Label',pvc.visual.Sign).init(function(panel,protoMark,keyArgs){var pvMark=protoMark.add(pv.Label);this.base(panel,pvMark,keyArgs)}).add({_addInteractive:function(keyArgs){keyArgs=def.setDefaults(keyArgs,'noSelect',true,'noHover',true,'noTooltip',true,'noClick',true,'noDoubleClick',true);this.base(keyArgs)},defaultColor:function(type){return pv.Color.names.black}}); -def.type('pvc.visual.Dot',pvc.visual.Sign).init(function(panel,parentMark,keyArgs){var pvMark=parentMark.add(pv.Dot);var protoMark=def.get(keyArgs,'proto');if(protoMark){pvMark.extend(protoMark)}keyArgs=def.setDefaults(keyArgs,'freeColor',false);this.base(panel,pvMark,keyArgs);if(!def.get(keyArgs,'freePosition',false)){var basePosProp=panel.isOrientationVertical()?"left":"bottom",orthoPosProp=panel.anchorOrtho(basePosProp);this._lockDynamic(orthoPosProp,'y')._lockDynamic(basePosProp,'x')}this._bindProperty('shape','shape')._bindProperty('shapeRadius','radius')._bindProperty('shapeSize','size').optional('strokeDasharray',undefined).optional('lineWidth',1.5)}).prototype.property('size').constructor.add({y:function(){return 0},x:function(){return 0},shape:function(){return this.delegateExtension()},radius:function(){this.state.radius=this.delegateExtension()},baseSize:function(){var radius=this.state.radius;if(radius!=null){return radius*radius}return this.base()},defaultSize:function(){return 12},interactiveSize:function(size){if(this.scene.isActive){return Math.max(size,5)*2.5}return size},interactiveColor:function(color,type){var scene=this.scene;if(scene.isActive){if(type==='stroke'){return color.brighter(1)}}else if(this.showsSelection()&&scene.anySelected()&&!scene.isSelected()){if(this.isActiveSeriesAware&&scene.isActiveSeries()){return color.alpha(0.8)}else{switch(type){case'fill':return this.dimColor(color,type);case'stroke':return color.alpha(0.45)}}}return this.base(color,type)}}); -def.type('pvc.visual.Line',pvc.visual.Sign).init(function(panel,protoMark,keyArgs){var pvMark=protoMark.add(pv.Line);this.base(panel,pvMark,keyArgs);this.lock('segmented','smart').lock('antialias',true);if(!def.get(keyArgs,'freePosition',false)){var basePosProp=panel.isOrientationVertical()?"left":"bottom",orthoPosProp=panel.anchorOrtho(basePosProp);this._lockDynamic(orthoPosProp,'y')._lockDynamic(basePosProp,'x')}this._bindProperty('strokeStyle','strokeColor','color')._bindProperty('lineWidth','strokeWidth')}).prototype.property('strokeWidth').constructor.add({_addInteractive:function(keyArgs){keyArgs=def.setDefaults(keyArgs,'noTooltip',true);this.base(keyArgs)},y:function(){return 0},x:function(){return 0},defaultStrokeWidth:function(){return 1.5},interactiveStrokeWidth:function(strokeWidth){if(this.isActiveSeriesAware&&this.scene.isActiveSeries()){return Math.max(1,strokeWidth)*2.5}return strokeWidth},interactiveColor:function(color,type){var scene=this.scene;if(this.showsSelection()&&scene.anySelected()&&!scene.isSelected()){if(this.isActiveSeriesAware&&scene.isActiveSeries()){return pv.Color.names.darkgray.darker().darker()}if(type==='stroke'){return this.dimColor(color,type)}}return this.base(color,type)}}); -def.type('pvc.visual.Area',pvc.visual.Sign).init(function(panel,protoMark,keyArgs){var pvMark=protoMark.add(pv.Area);if(!keyArgs){keyArgs={}}keyArgs.freeColor=true;this.base(panel,pvMark,keyArgs);var antialias=def.get(keyArgs,'antialias',true);this.lock('segmented','smart').lock('antialias',antialias);if(!def.get(keyArgs,'freePosition',false)){var basePosProp=panel.isOrientationVertical()?"left":"bottom",orthoPosProp=panel.anchorOrtho(basePosProp),orthoLenProp=panel.anchorOrthoLength(orthoPosProp);this._lockDynamic(basePosProp,'x')._lockDynamic(orthoPosProp,'y')._lockDynamic(orthoLenProp,'dy')}this._bindProperty('fillStyle','fillColor','color');this.lock('strokeStyle',null).lock('lineWidth',0)}).add({_addInteractive:function(keyArgs){keyArgs=def.setDefaults(keyArgs,'noTooltip',true);this.base(keyArgs)},x:function(){return 0},y:function(){return 0},dy:function(){return 0},interactiveColor:function(color,type){if(type==='fill'&&this.showsSelection()&&this.scene.anySelected()&&!this.scene.isSelected()){return this.dimColor(color,type)}return this.base(color,type)}}); -def.type('pvc.visual.Bar',pvc.visual.Sign).init(function(panel,protoMark,keyArgs){var pvMark=protoMark.add(pv.Bar);keyArgs=def.setDefaults(keyArgs,'freeColor',false);this.base(panel,pvMark,keyArgs);this.normalStroke=def.get(keyArgs,'normalStroke',false);this._bindProperty('lineWidth','strokeWidth')}).prototype.property('strokeWidth').constructor.add({normalColor:function(color,type){if(type==='stroke'&&!this.normalStroke){return null}return color},interactiveColor:function(color,type){var scene=this.scene;if(type==='stroke'){if(scene.isActive){return color.brighter(1.3).alpha(0.7)}if(!this.normalStroke){return null}if(this.showsSelection()&&scene.anySelected()&&!scene.isSelected()){if(this.isActiveSeriesAware&&scene.isActiveSeries()){return pv.Color.names.darkgray.darker().darker()}return this.dimColor(color,type)}if(this.isActiveSeriesAware&&scene.isActiveSeries()){return color.brighter(1).alpha(0.7)}}else if(type==='fill'){if(scene.isActive){return color.brighter(0.2).alpha(0.8)}if(this.showsSelection()&&scene.anySelected()&&!scene.isSelected()){if(this.isActiveSeriesAware&&scene.isActiveSeries()){return pv.Color.names.darkgray.darker(2).alpha(0.8)}return this.dimColor(color,type)}if(this.isActiveSeriesAware&&scene.isActiveSeries()){return color.brighter(0.2).alpha(0.8)}}return this.base(color,type)},defaultStrokeWidth:function(){return 0.5},interactiveStrokeWidth:function(strokeWidth){if(this.scene.isActive){return Math.max(1,strokeWidth)*1.3}return strokeWidth}}); -pv.PieSlice=function(){pv.Wedge.call(this)};pv.PieSlice.prototype=pv.extend(pv.Wedge);pv.PieSlice.prototype.midAngle=function(){var instance=this.instance();return instance.startAngle+(instance.angle/2)};def.type('pvc.visual.PieSlice',pvc.visual.Sign).init(function(panel,protoMark,keyArgs){var pvMark=protoMark.add(pv.PieSlice);keyArgs=def.setDefaults(keyArgs,'freeColor',false);this.base(panel,pvMark,keyArgs);this._activeOffsetRadius=def.get(keyArgs,'activeOffsetRadius',0);this._center=def.get(keyArgs,'center');this.optional('lineWidth',0.6)._bindProperty('angle','angle')._lockDynamic('bottom','y')._lockDynamic('left','x').lock('top',null).lock('right',null)}).prototype.property('offsetRadius').constructor.add({angle:function(){return 0},x:function(){return this._center.x+this._offsetSlice('cos')},y:function(){return this._center.y-this._offsetSlice('sin')},_offsetSlice:function(fun){var offset=this._getOffsetRadius();if(offset!==0){offset=offset*Math[fun](this.pvMark.midAngle())}return offset},_getOffsetRadius:function(){var offset=this.state.offsetRadius;if(offset==null){offset=(this.state.offsetRadius=this.offsetRadius()||0)}return offset},defaultColor:function(type){if(type==='stroke'){return null}return this.base(type)},interactiveColor:function(color,type){var scene=this.scene;if(scene.isActive){switch(type){case'fill':return color.brighter(0.2).alpha(0.8);case'stroke':return color.brighter(1.3).alpha(0.7)}}else if(this.showsSelection()&&scene.anySelected()&&!scene.isSelected()){if(type==='fill'){return this.dimColor(color,type)}}return this.base(color,type)},baseOffsetRadius:function(){return 0},interactiveOffsetRadius:function(offsetRadius){if(this.scene.isActive){return offsetRadius+this._activeOffsetRadius}return offsetRadius}}); -def.type('pvc.visual.Rule',pvc.visual.Sign).init(function(panel,parentMark,keyArgs){var pvMark=parentMark.add(pv.Rule);var protoMark=def.get(keyArgs,'proto');if(protoMark){pvMark.extend(protoMark)}this.base(panel,pvMark,keyArgs);if(!def.get(keyArgs,'freeStyle')){this._bindProperty('strokeStyle','strokeColor','color')._bindProperty('lineWidth','strokeWidth')}}).prototype.property('strokeWidth').constructor.add({_addInteractive:function(keyArgs){keyArgs=def.setDefaults(keyArgs,'noHover',true,'noSelect',true,'noTooltip',true,'noClick',true,'noDoubleClick',true);this.base(keyArgs)},defaultStrokeWidth:function(){return 1},interactiveStrokeWidth:function(strokeWidth){if(this.scene.isActive){return Math.max(1,strokeWidth)*2.2}return strokeWidth},interactiveColor:function(color,type){var scene=this.scene;if(!scene.isActive&&this.showsSelection()&&scene.anySelected()&&scene.datum&&!scene.isSelected()){return this.dimColor(color,type)}return this.base(color,type)}}); -def.type('pvc.visual.Context').init(function(panel,mark,event){this.chart=panel.chart;this.panel=panel;visualContext_update.call(this,mark,event)}).add({isPinned:false,pin:function(){this.isPinned=true;return this},finished:function(v){return this.sign.finished(v)},delegate:function(dv){return this.sign.delegate(dv)},getV1Series:function(){var s;var series=this.scene.firstAtoms&&(s=this.scene.firstAtoms[this.panel._getV1DimName('series')])&&s.rawValue;if(series==null){series='Series'}return series},getV1Category:function(){var c;return this.scene.firstAtoms&&(c=this.scene.firstAtoms[this.panel._getV1DimName('category')])&&c.rawValue},getV1Value:function(){var v;return this.scene.firstAtoms&&(v=this.scene.firstAtoms[this.panel._getV1DimName('value')])&&v.value},getV1Datum:function(){return this.panel._getV1Datum(this.scene)}});if(Object.defineProperty){try{Object.defineProperty(pvc.visual.Context.prototype,'parent',{get:function(){throw def.error.operationInvalid("The 'this.parent.index' idiom has no equivalent in this version. Please try 'this.pvMark.parent.index'.")}})}catch(ex){}}function visualContext_update(mark,event){this.event=event||null;this.pvMark=mark;var scene;if(mark){var sign=this.sign=mark.sign||null;if(sign){scene=mark.instance().data}if(!scene){this.index=null;scene=new pvc.visual.Scene(null,{panel:this.panel})}else{this.index=scene.childIndex()}}else{this.sign=null;this.index=null;scene=new pvc.visual.Scene(null,{panel:this.panel,group:this.chart.root.data})}this.scene=scene} -def.type('pvc.visual.OptionsBase').init(function(chart,type,index,keyArgs){this.chart=chart;this.type=type;this.index=index==null?0:index;this.name=def.get(keyArgs,'name');this.id=this._buildId();this.optionId=this._buildOptionId();var rs=this._resolvers=[];this._registerResolversFull(rs,keyArgs);this.option=pvc.options(this._getOptionsDefinition(),this)}).add({_buildId:function(){return pvc.buildIndexedId(this.type,this.index)},_buildOptionId:function(){return this.id},_getOptionsDefinition:def.method({isAbstract:true}),_chartOption:function(name){return this.chart.options[name]},_registerResolversFull:function(rs,keyArgs){var fixed=def.get(keyArgs,'fixed');if(fixed){this._fixed=fixed;rs.push(pvc.options.specify(function(optionInfo){return fixed[optionInfo.name]}))}this._registerResolversNormal(rs,keyArgs);var defaults=def.get(keyArgs,'defaults');if(defaults){this._defaults=defaults}rs.push(this._resolveDefault)},_registerResolversNormal:function(rs,keyArgs){if(this.chart.compatVersion()<=1){rs.push(this._resolveByV1OnlyLogic)}if(this.name){rs.push(pvc.options.specify(function(optionInfo){return this._chartOption(this.name+def.firstUpperCase(optionInfo.name))}))}rs.push(this._resolveByOptionId);if(def.get(keyArgs,'byNaked',!this.index)){rs.push(this._resolveByNaked)}},_resolveFull:function(optionInfo){var rs=this._resolvers;for(var i=0,L=rs.length;i1){var grouping=this.role.grouping,i;if(this.scaleType==='discrete'){for(i=1;i0){var bandRatio=this.chart.options.panelSizeRatio||0.8;scale.splitBandedCenter(scale.min,scale.max,bandRatio)}}else{scale.range(scale.min,scale.max)}if(pvc.debug>4){this.chart._log("Axis "+this.id+" setRange: "+pvc.stringify(scale.range()))}return scale},getScaleRoundingPaddings:function(){var roundingPaddings=this._roundingPaddings;if(!roundingPaddings){roundingPaddings={begin:0,end:0,beginLocked:false,endLocked:false};var scale=this.scale;if(scale&&!scale.isNull&&scale.type!=='discrete'){var originalDomain=this.domain;roundingPaddings.beginLocked=originalDomain.minLocked;roundingPaddings.endLocked=originalDomain.maxLocked;if(scale.type==='numeric'&&this.option('DomainRoundMode')!=='none'){var currDomain=scale.domain();var origDomain=this.domain||def.assert("Original domain must be set");var currLength=currDomain[1]-currDomain[0];if(currLength){var diff=origDomain[0]-currDomain[0];if(diff>0){roundingPaddings.begin=diff/currLength}diff=currDomain[1]-origDomain[1];if(diff>0){roundingPaddings.end=diff/currLength}}}}this._roundingPaddings=roundingPaddings}return roundingPaddings},_getOptionsDefinition:function(){return cartAxis_optionsDef},_buildOptionId:function(){return this.id+"Axis"},_registerResolversNormal:function(rs,keyArgs){if(this.chart.compatVersion()<=1){rs.push(this._resolveByV1OnlyLogic)}rs.push(this._resolveByOptionId,this._resolveByOrientedId);if(this.index===1){rs.push(this._resolveByV1OptionId)}rs.push(this._resolveByScaleType,this._resolveByCommonId)},_resolveByOrientedId:pvc.options.specify(function(optionInfo){return this._chartOption(this.orientedId+"Axis"+optionInfo.name)}),_resolveByV1OptionId:pvc.options.specify(function(optionInfo){return this._chartOption('secondAxis'+optionInfo.name)}),_resolveByScaleType:pvc.options.specify(function(optionInfo){var st=this.scaleType;if(st){var name=optionInfo.name;var value=this._chartOption(st+'Axis'+name);if(value===undefined&&st!=='discrete'){value=this._chartOption('continuousAxis'+name)}return value}}),_resolveByCommonId:pvc.options.specify(function(optionInfo){return this._chartOption('axis'+optionInfo.name)})});var $VCA=pvc.visual.CartesianAxis;$VCA.getOrientation=function(type,chartOrientation){return((type==='base')===(chartOrientation==='vertical'))?'x':'y'};$VCA.getOrientedId=function(orientation,index){if(index===0){return orientation}return orientation+(index+1)};var fixedMinMaxSpec={resolve:'_resolveFull',data:{resolveV1:function(optionInfo){if(!this.index&&this.type==='ortho'){this._specifyChartOption(optionInfo,this.id+optionInfo.name)}return true}},cast:pvc.castNumber};function castDomainScope(scope,axis){return pvc.parseDomainScope(scope,axis.orientation)}function castAxisPosition(side){if(side){if(def.hasOwn(pvc.Sides.namesSet,side)){var mapAlign=pvc.BasePanel[this.orientation==='y'?'horizontalAlign':'verticalAlign2'];return mapAlign[side]}if(pvc.debug>=2){pvc.log(def.format("Invalid axis position value '{0}'.",[side]))}}return this.orientation==='x'?'bottom':'left'}var normalV1Data={resolveV1:function(optionInfo){if(!this.index){if(this._resolveByOrientedId(optionInfo)){return true}}else if(this._resolveByV1OptionId(optionInfo)){return true}this._resolveDefault(optionInfo);return true}};var defaultPosition=pvc.options.defaultValue(function(optionInfo){if(!this.typeIndex){return this.orientation==='x'?'bottom':'left'}var firstAxis=this.chart.axesByType[this.type].first;var position=firstAxis.option('Position');return pvc.BasePanel.oppositeAnchor[position]});function castSize(value){var position=this.option('Position');return pvc.Size.toOrtho(value,position)}function castTitleSize(value){var position=this.option('Position');return pvc.Size.to(value,{singleProp:pvc.BasePanel.orthogonalLength[position]})}var cartAxis_optionsDef=def.create(axis_optionsDef,{Visible:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){if(this.index<=1){var v1OptionId=this.index===0?def.firstUpperCase(this.orientation):'Second';this._specifyChartOption(optionInfo,'show'+v1OptionId+'Scale')}return true}},cast:Boolean,value:true},Composite:{resolve:function(optionInfo){if(this.index>0){optionInfo.specify(false);return true}return this._resolveFull(optionInfo)},data:{resolveV1:function(optionInfo){this._specifyChartOption(optionInfo,'useCompositeAxis');return true}},cast:Boolean,value:false},Size:{resolve:'_resolveFull',data:normalV1Data,cast:castSize},SizeMax:{resolve:'_resolveFull',cast:castSize},Position:{resolve:'_resolveFull',data:{resolveV1:normalV1Data.resolveV1,resolveDefault:defaultPosition},cast:castAxisPosition},FixedMin:fixedMinMaxSpec,FixedMax:fixedMinMaxSpec,OriginIsZero:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){switch(this.index){case 0:this._specifyChartOption(optionInfo,'originIsZero');break;case 1:if(this.chart._allowV1SecondAxis){this._specifyChartOption(optionInfo,'secondAxisOriginIsZero')}break}return true}},cast:Boolean,value:true},DomainScope:{resolve:'_resolveFull',cast:castDomainScope,value:'global'},Offset:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){switch(this.index){case 0:this._specifyChartOption(optionInfo,'axisOffset');break;case 1:if(this.chart._allowV1SecondAxis){this._specifyChartOption(optionInfo,'secondAxisOffset');break}break}return true}},cast:pvc.castNumber},LabelSpacingMin:{resolve:'_resolveFull',cast:pvc.castNumber},OverlappedLabelsMode:{resolve:'_resolveFull',cast:pvc.parseOverlappedLabelsMode,value:'hide'},Grid:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){if(!this.index){this._specifyChartOption(optionInfo,this.orientation+'AxisFullGrid')}return true}},cast:Boolean,value:false},GridCrossesMargin:{resolve:'_resolveFull',cast:Boolean,value:true},EndLine:{resolve:'_resolveFull',cast:Boolean},ZeroLine:{resolve:'_resolveFull',cast:Boolean,value:true},RuleCrossesMargin:{resolve:'_resolveFull',cast:Boolean,value:true},Ticks:{resolve:'_resolveFull',cast:Boolean},DesiredTickCount:{resolve:'_resolveFull',data:{resolveV1:normalV1Data.resolveV1,resolveDefault:function(optionInfo){if(this.chart.compatVersion()<=1){optionInfo.defaultValue(5);return true}}},cast:pvc.castNumber},MinorTicks:{resolve:'_resolveFull',data:normalV1Data,cast:Boolean,value:true},TickFormatter:{resolve:'_resolveFull',cast:def.fun.as},DomainRoundMode:{resolve:'_resolveFull',data:{resolveV1:normalV1Data.resolveV1,resolveDefault:function(optionInfo){if(this.chart.compatVersion()<=1){optionInfo.defaultValue('none');return true}}},cast:pvc.parseDomainRoundingMode,value:'tick'},TickExponentMin:{resolve:'_resolveFull',cast:pvc.castNumber},TickExponentMax:{resolve:'_resolveFull',cast:pvc.castNumber},Title:{resolve:'_resolveFull',cast:String},TitleSize:{resolve:'_resolveFull',cast:castTitleSize},TitleSizeMax:{resolve:'_resolveFull',cast:castTitleSize},TitleFont:{resolve:'_resolveFull',cast:String},TitleMargins:{resolve:'_resolveFull',cast:pvc.Sides.as},TitlePaddings:{resolve:'_resolveFull',cast:pvc.Sides.as},TitleAlign:{resolve:'_resolveFull',cast:function castAlign(align){var position=this.option('Position');return pvc.parseAlign(position,align)}},Font:{resolve:'_resolveFull',cast:String},ClickAction:{resolve:'_resolveFull',data:normalV1Data},DoubleClickAction:{resolve:'_resolveFull',data:normalV1Data}})}); -def.type('pvc.visual.CartesianAxisRootScene',pvc.visual.Scene); -def.type('pvc.visual.CartesianAxisTickScene',pvc.visual.Scene).init(function(parent,keyArgs){this.base(parent,keyArgs);this.vars.tick=new pvc.visual.ValueLabelVar(def.get(keyArgs,'tick'),def.get(keyArgs,'tickLabel'),def.get(keyArgs,'tickRaw'))}); -def.scope(function(){def.type('pvc.visual.CartesianFocusWindow',pvc.visual.OptionsBase).init(function(chart){this.base(chart,'focusWindow',0,{byNaked:false});var baseAxis=chart.axes.base;this.base=new pvc.visual.CartesianFocusWindowAxis(this,baseAxis)}).add({_getOptionsDefinition:function(){return focusWindow_optionsDef},_exportData:function(){return{base:def.copyProps(this.base,pvc.visual.CartesianFocusWindow.props)}},_importData:function(data){var baseData=data.base;this.base.option.specify({Begin:baseData.begin,End:baseData.end,Length:baseData.length})},_initFromOptions:function(){this.base._initFromOptions()},_onAxisChanged:function(axis){var changed=this.option('Changed');if(changed){changed.call(this.chart.basePanel._getContext())}}});var focusWindow_optionsDef=def.create(axis_optionsDef,{Changed:{resolve:'_resolveFull',cast:def.fun.as}});def.type('pvc.visual.CartesianFocusWindowAxis',pvc.visual.OptionsBase).init(function(fw,axis){this.window=fw;this.axis=axis;this.isDiscrete=axis.isDiscrete();this.base(axis.chart,'focusWindow'+def.firstUpperCase(axis.type),0,{byNaked:false})}).addStatic({props:['begin','end','length']}).add({_getOptionsDefinition:function(){return focusWindowAxis_optionsDef},_initFromOptions:function(){var o=this.option;this.set({begin:o('Begin'),end:o('End'),length:o('Length')})},set:function(keyArgs){var me=this;var render=def.get(keyArgs,'render');var select=def.get(keyArgs,'select',true);var b,e,l;keyArgs=me._readArgs(keyArgs);if(!keyArgs){if(this.begin!=null&&this.end!=null&&this.length!=null){return}}else{b=keyArgs.begin;e=keyArgs.end;l=keyArgs.length}var axis=me.axis;var scale=axis.scale;var isDiscrete=me.isDiscrete;var contCast=!isDiscrete?axis.role.firstDimensionType().cast:null;var domain=scale.domain();var a,L;if(isDiscrete){L=domain.length;var ib,ie,ia;if(b!=null){var nb=+b;if(!isNaN(nb)){if(nb===Infinity){ib=L-1;b=domain[ib]}else if(nb===-Infinity){ib=0;b=domain[ib]}}if(ib==null){ib=domain.indexOf(''+b);if(ib<0){ib=0;b=domain[ib]}}}if(e!=null){var ne=+e;if(!isNaN(ne)){if(ne===Infinity){ie=L-1;e=domain[ie]}else if(ne===-Infinity){ie=0;e=domain[ie]}}if(ie==null){ie=domain.indexOf(''+e);if(ie<0){ie=L-1;e=domain[ie]}}}if(l!=null){l=+l;if(isNaN(l)){l=null}else if(l<0&&(b!=null||e!=null)){a=b;ia=ib;b=e,ib=ie,e=a,ie=ia;l=-l}}if(b!=null){if(e!=null){if(ib>ie){a=b;ia=ib;b=e,ib=ie,e=a,ie=ia}l=ie-ib+1}else{if(l==null){l=L-ib}ie=ib+l-1;if(ie>L-1){ie=L-1;l=ie-ib+1}e=domain[ie]}}else{if(e!=null){if(l==null){l=ie}ib=ie-l+1;if(ib<0){ib=0;l=ie-ib+1}b=domain[ib]}else{if(l==null){l=Math.max(~~(L/3),1); }if(l>L){l=L;ib=0;ie=L-1}else{ia=~~(L/2); ib=ia-~~(l/2);ie=ib+l-1}b=domain[ib];e=domain[ie]}}}else{if(l!=null){l=+l;if(isNaN(l)){l=null}else if(l<0&&(b!=null||e!=null)){a=b;b=e,e=a;l=-l}}var min=domain[0];var max=domain[1];L=max-min;if(b!=null){if(bmax){b=max}}if(e!=null){if(emax){e=max}}if(b!=null){if(e!=null){if(b>e){a=b;b=e,e=a}l=e-b}else{if(l==null){l=max-b}e=b+l;if(e>max){e=max;l=e-b}}}else{if(e!=null){if(l==null){l=e-min}b=e-l;if(bL){l=L;b=min;e=max}else{a=~~(L/2); b=a-~~(l/2);e=(+b)+(+l)}}}b=contCast(b);e=contCast(e);l=contCast(l);var constraint=me.option('Constraint');if(constraint){var oper2={type:'new',target:'begin',value:b,length:l,length0:l,min:min,max:max,minView:min,maxView:max};constraint(oper2);b=contCast(oper2.value);l=contCast(oper2.length);e=contCast((+b)+(+l))}}me._set(b,e,l,select,render)},_updatePosition:function(pbeg,pend,select,render){var me=this;var axis=me.axis;var scale=axis.scale;var b,e,l;if(me.isDiscrete){var ib=scale.invertIndex(pbeg);var ie=scale.invertIndex(pend)-1;var domain=scale.domain();b=domain[ib];e=domain[ie];l=ie-ib+1}else{b=scale.invert(pbeg);e=scale.invert(pend);l=e-b}this._set(b,e,l,select,render)},_constraintPosition:function(oper){var me=this;var axis=me.axis;var scale=axis.scale;var constraint;if(me.isDiscrete){var index=Math.floor(scale.invertIndex(oper.point,true));if(index>=0){var r=scale.range();var L=scale.domain().length;var S=(r.max-r.min)/L;if(index>=L&&(oper.type==='new'||oper.type==='resize-begin')){index=L-1}oper.point=index*S}}else if((constraint=me.option('Constraint'))){var contCast=axis.role.firstDimensionType().cast;var v=contCast(scale.invert(oper.point));var sign=oper.target==='begin'?1:-1;var pother=oper.point+sign*oper.length;var vother=contCast(scale.invert(pother));var vlength=contCast(sign*(vother-v));var vlength0,pother0,vother0;if(oper.length===oper.length0){vlength0=vlength}else{pother0=oper.point+sign*oper.length0;vother0=contCast(scale.invert(pother0));vlength0=sign*(vother0-v)}var vmin=contCast(scale.invert(oper.min));var vmax=contCast(scale.invert(oper.max));var oper2={type:oper.type,target:oper.target,value:v,length:vlength,length0:vlength0,min:vmin,max:vmax,minView:contCast(scale.invert(oper.minView)),maxView:contCast(scale.invert(oper.maxView))};constraint(oper2);if(+oper2.value!==+v){v=oper2.value;oper.point=scale(v)}var vlength2=oper2.length;if(+vlength2!==+vlength){if(+vlength2===+vlength0){oper.length=oper.length0}else{var vother2=(+v)+sign*(+vlength2);var pother2=scale(vother2);oper.length=pother2-sign*oper.point}}if(+oper2.min!==+vmin){oper.min=scale(oper2.min)}if(+oper2.max!==+vmax){oper.max=scale(oper2.max)}}},_compare:function(a,b){return this.isDiscrete?((''+a)===(''+b)):((+a)===(+b))},_set:function(b,e,l,select,render){var me=this;var changed=false;if(!me._compare(b,me.begin)){me.begin=b;changed=true}if(!me._compare(e,me.end)){me.end=e;changed=true}if(!me._compare(l,me.length)){me.length=l;changed=true}if(changed){me.window._onAxisChanged(this)}if(select){me._updateSelection({render:render})}return changed},_readArgs:function(keyArgs){if(keyArgs){var out={};var any=0;var read=function(p){var v=keyArgs[p];if(v!=null){any=true}else{v=this[p]}out[p]=v};pvc.visual.CartesianFocusWindowAxis.props.forEach(read,this);if(any){return out}}},_updateSelection:function(keyArgs){var me=this;var selectDatums;var axis=me.axis;var isDiscrete=axis.isDiscrete();var chart=axis.chart;var dataCell=axis.dataCell;var role=dataCell.role;var partData=chart.partData(dataCell.dataPartValue,{visible:true});var domainData;if(isDiscrete){domainData=partData.flattenBy(role);var dataBegin=domainData._childrenByKey[me.begin];var dataEnd=domainData._childrenByKey[me.end];if(dataBegin&&dataEnd){var indexBegin=dataBegin.childIndex();var indexEnd=dataEnd.childIndex();selectDatums=def.range(indexBegin,indexEnd-indexBegin+1).select(function(index){return domainData._children[index]}).selectMany(function(data){return data._datums}).distinct(function(datum){return datum.key})}}else{domainData=partData;var dimName=role.firstDimensionName();selectDatums=def.query(partData._datums).where(function(datum){var v=datum.atoms[dimName].value;return v!=null&&v>=me.begin&&v<=me.end})}if(selectDatums){chart.data.replaceSelected(selectDatums);chart.root.updateSelections(keyArgs)}}});var focusWindowAxis_optionsDef=def.create(axis_optionsDef,{Resizable:{resolve:'_resolveFull',cast:Boolean,value:true},Movable:{resolve:'_resolveFull',cast:Boolean,value:true},Begin:{resolve:'_resolveFull'},End:{resolve:'_resolveFull'},Length:{resolve:'_resolveFull'},Constraint:{resolve:'_resolveFull',cast:def.fun.as}})}); -def.scope(function(){def.type('pvc.visual.ColorAxis',pvc.visual.Axis).add({scaleNullRangeValue:function(){return this.option('Missing')||null},scaleUsesAbs:function(){return this.option('UseAbs')},bind:function(dataCells){this.base(dataCells);this._plotList=def.query(dataCells).select(function(dataCell){return dataCell.plot}).distinct(function(plot){return plot&&plot.id}).array();return this},calculateScale:function(){var scale,noWrap;var dataCells=this.dataCells;if(dataCells){var chart=this.chart;if(this.scaleType==='discrete'){var domainValues=def.query(dataCells).selectMany(function(dataCell){var role=dataCell.role;if(role&&role.isBound()){var partData=chart.partData(dataCell.dataPartValue);var domainData=partData&&partData.flattenBy(role);dataCell.data=domainData;return domainData&&domainData.children()}}).distinct(function(child){return child.key}).select(function(child){return def.nullyTo(child.value,'')}).array();this.domainValues=domainValues;scale=this.scheme()(domainValues);noWrap=true}else{if(dataCells.length===1){var visibleDomainData=chart.root.visibleData(this.dataCell.dataPartValue);var normByCateg=this.option('NormByCategory');var scaleOptions={type:this.option('ScaleType'),colors:this.option('Colors')().range(),colorDomain:this.option('Domain'),colorMin:this.option('Min'),colorMax:this.option('Max'),colorNull:this.option('Missing'),data:visibleDomainData,colorDimension:this.role.firstDimensionName(),normPerBaseCategory:normByCateg};if(normByCateg){this.scalesByCateg=pvc.color.scales(scaleOptions)}else{scale=pvc.color.scale(scaleOptions)}}}}this.setScale(scale,noWrap);return this},_wrapScale:function(scale){var applyTransf;if(this.scaleType==='discrete'){applyTransf=this.option.isSpecified('Transform')||(!this.option.isSpecified('Colors')&&!this.option.isSpecified('Map'))}else{applyTransf=true}if(applyTransf){var colorTransf=this.option('Transform');if(colorTransf){scale=scale.transform(colorTransf)}}return this.base(scale)},scheme:function(){return def.lazy(this,'_scheme',this._createScheme,this)},_createColorMapFilter:function(colorMap){var fixedColors=def.uniqueIndex(colorMap,function(c){return c.key});return{domain:function(k){return!def.hasOwn(colorMap,k)},color:function(c){return!def.hasOwn(fixedColors,c.key)}}},_createScheme:function(){var me=this;var baseScheme=me.option('Colors');if(me.scaleType!=='discrete'){return function(d){var scale=baseScheme.apply(null,arguments);return me._wrapScale(scale)}}var colorMap=me.option('Map');if(!colorMap){return function(d){var scale=baseScheme.apply(null,arguments);return me._wrapScale(scale)}}var filter=this._createColorMapFilter(colorMap);return function(d){var scale;if(!(d instanceof Array)){d=def.array.copy(arguments)}d=d.filter(filter.domain);var baseScale=baseScheme(d);var r=baseScale.range().filter(filter.color);baseScale.range(r);scale=function(k){var c=def.getOwn(colorMap,k);return c||baseScale(k)};def.copy(scale,baseScale);var dx,rx;scale.domain=function(){if(arguments.length){throw def.operationInvalid("The scale cannot be modified.")}if(!dx){dx=def.array.append(def.ownKeys(colorMap),d)}return dx};scale.range=function(){if(arguments.length){throw def.operationInvalid("The scale cannot be modified.")}if(!rx){rx=def.array.append(def.own(colorMap),d)}return rx};return me._wrapScale(scale)}},sceneScale:function(keyArgs){var varName=def.get(keyArgs,'sceneVarName')||this.role.name;return this.scale.by1(function(scene){return scene.vars[varName].value})},_buildOptionId:function(){return this.id+"Axis"},_getOptionsDefinition:function(){return colorAxis_optionsDef},_resolveByNaked:pvc.options.specify(function(optionInfo){if(!this.index){return this._chartOption(this.id+def.firstUpperCase(optionInfo.name))}}),_specifyV1ChartOption:function(optionInfo,asName){if(!this.index&&this.chart.compatVersion()<=1&&this._specifyChartOption(optionInfo,asName)){return true}}});function castSize(size){if(!def.object.is(size)){var position=this.option('Position');size=new pvc.Size().setSize(size,{singleProp:pvc.BasePanel.orthogonalLength[position]})}return size}function castAlign(align){var position=this.option('Position');return pvc.parseAlign(position,align)}function castColorMap(colorMap){var resultMap;if(colorMap){var any;def.eachOwn(colorMap,function(v,k){any=true;colorMap[k]=pv.color(v)});if(any){resultMap=colorMap}}return resultMap}var legendData={resolveDefault:function(optionInfo){if(!this.index&&this._specifyChartOption(optionInfo,def.firstLowerCase(optionInfo.name))){return true}}};function getDefaultColor(optionInfo){var colors;if(this.scaleType==='discrete'){if(this.index===0){colors=pvc.createColorScheme()}else{var me=this;colors=function(){return me.chart._getRoleColorScale(me.role.name)}}}else{colors=['red','yellow','green'].map(function(name){return pv.Color.names[name]})}return colors}var colorAxis_optionsDef=def.create(axis_optionsDef,{Colors:{resolve:'_resolveFull',getDefault:getDefaultColor,data:{resolveV1:function(optionInfo){if(this.scaleType==='discrete'){if(this.index===0){this._specifyChartOption(optionInfo,'colors')}else if(this.index===1&&this.chart._allowV1SecondAxis){this._specifyChartOption(optionInfo,'secondAxisColor')}}else{this._specifyChartOption(optionInfo,'colorRange')}return true},resolveDefault:function(optionInfo){if(this.index===0){this._specifyChartOption(optionInfo,'colors')}}},cast:pvc.colorScheme},Map:{resolve:'_resolveFull',cast:castColorMap},Transform:{resolve:'_resolveFull',data:{resolveDefault:function(optionInfo){var plotList=this._plotList;if(plotList.length<=2){var onlyTrendAndPlot2=def.query(plotList).all(function(plot){var name=plot.name;return(name==='plot2'||name==='trend')});if(onlyTrendAndPlot2){optionInfo.defaultValue(pvc.brighterColorTransform);return true}}}},cast:def.fun.to},NormByCategory:{resolve:function(optionInfo){if(!this.chart._allowColorPerCategory){optionInfo.specify(false);return true}return this._resolveFull(optionInfo)},data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'normPerBaseCategory');return true}},cast:Boolean,value:false},ScaleType:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'scalingType');return true}},cast:pvc.parseContinuousColorScaleType,value:'linear'},UseAbs:{resolve:'_resolveFull',cast:Boolean,value:false},Domain:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'colorRangeInterval');return true}},cast:def.array.to},Min:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'minColor');return true}},cast:pv.color},Max:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'maxColor');return true}},cast:pv.color},Missing:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'nullColor');return true}},cast:pv.color,value:pv.color("#efc5ad")},LegendVisible:{resolve:'_resolveFull',data:legendData,cast:Boolean,value:true},LegendClickMode:{resolve:'_resolveFull',data:legendData,cast:pvc.parseLegendClickMode,value:'toggleVisible'},LegendDrawLine:{resolve:'_resolveFull',data:legendData,cast:Boolean,value:false},LegendDrawMarker:{resolve:'_resolveFull',data:legendData,cast:Boolean,value:true},LegendShape:{resolve:'_resolveFull',data:legendData,cast:pvc.parseShape}})}); -var sizeAxis_optionsDef;def.scope(function(){def.type('pvc.visual.SizeAxis',pvc.visual.Axis).init(function(chart,type,index,keyArgs){keyArgs=def.set(keyArgs,'byNaked',false);this.base(chart,type,index,keyArgs)}).add({scaleTreatsNullAs:function(){return'min'},scaleUsesAbs:function(){return this.option('UseAbs')},setScaleRange:function(range){var scale=this.scale;scale.min=range.min;scale.max=range.max;scale.size=range.max-range.min;scale.range(scale.min,scale.max);if(pvc.debug>=4){pvc.log("Scale: "+pvc.stringify(def.copyOwn(scale)))}return this},_getOptionsDefinition:function(){return sizeAxis_optionsDef}});sizeAxis_optionsDef=def.create(axis_optionsDef,{OriginIsZero:{resolve:'_resolveFull',cast:Boolean,value:false},FixedMin:{resolve:'_resolveFull',cast:pvc.castNumber},FixedMax:{resolve:'_resolveFull',cast:pvc.castNumber},UseAbs:{resolve:'_resolveFull',cast:Boolean,value:false}})}); -def.scope(function(){def.type('pvc.visual.Legend',pvc.visual.OptionsBase).init(function(chart,type,index,keyArgs){keyArgs=def.set(keyArgs,'byNaked',false);this.base(chart,type,index,keyArgs)}).add({_getOptionsDefinition:function(){return legend_optionsDef}});function castSize(size){if(!def.object.is(size)){var position=this.option('Position');size=new pvc.Size().setSize(size,{singleProp:pvc.BasePanel.orthogonalLength[position]})}return size}function castAlign(align){var position=this.option('Position');return pvc.parseAlign(position,align)}var legend_optionsDef={Position:{resolve:'_resolveFull',cast:pvc.parsePosition,value:'bottom'},Size:{resolve:'_resolveFull',cast:castSize},SizeMax:{resolve:'_resolveFull',cast:castSize},Align:{resolve:'_resolveFull',data:{resolveDefault:function(optionInfo){var position=this.option('Position');var align;if(position!=='top'&&position!=='bottom'){align='top'}else if(this.chart.compatVersion()<=1){align='left'}optionInfo.defaultValue(align);return true}},cast:castAlign},Margins:{resolve:'_resolveFull',data:{resolveDefault:function(optionInfo){if(this.chart.compatVersion()>1){var position=this.option('Position');var margins=def.set({},pvc.BasePanel.oppositeAnchor[position],5);optionInfo.defaultValue(margins)}return true}},cast:pvc.Sides.as},Paddings:{resolve:'_resolveFull',cast:pvc.Sides.as,value:5},Font:{resolve:'_resolveFull',cast:String,value:'10px sans-serif'}}}); -def.type('pvc.visual.legend.BulletRootScene',pvc.visual.Scene).init(function(parent,keyArgs){this.base(parent,keyArgs);var markerDiam=def.get(keyArgs,'markerSize',15);var itemPadding=new pvc.Sides(def.get(keyArgs,'itemPadding',5)).resolve(markerDiam,markerDiam);def.set(this.vars,'horizontal',def.get(keyArgs,'horizontal',false),'font',def.get(keyArgs,'font'),'markerSize',markerDiam,'textMargin',def.get(keyArgs,'textMargin',6),'itemPadding',itemPadding)}).add({layout:function(layoutInfo){var clientSize=layoutInfo.clientSize;if(!(clientSize.width>0&&clientSize.height>0)){return new pvc.Size(0,0)}var desiredClientSize=layoutInfo.desiredClientSize;var markerDiam=this.vars.markerSize;var textLeft=markerDiam+this.vars.textMargin;var itemPadding=this.vars.itemPadding;var a_width=this.vars.horizontal?'width':'height';var a_height=pvc.BasePanel.oppositeLength[a_width];var maxRowWidth=desiredClientSize[a_width];if(!maxRowWidth||maxRowWidth<0){maxRowWidth=clientSize[a_width]}var row;var rows=[];var contentSize={width:0,height:0};this.childNodes.forEach(function(groupScene){groupScene.childNodes.forEach(layoutItem,this)},this);if(!row){return new pvc.Size(0,0)}commitRow(true);def.set(this.vars,'rows',rows,'rowCount',row,'size',contentSize);var isV1Compat=this.compatVersion()<=1;var w=isV1Compat?maxRowWidth:contentSize.width;var h=desiredClientSize[a_height];if(!h||h<0){h=contentSize.height}return def.set({},a_width,Math.min(w,clientSize[a_width]),a_height,Math.min(h,clientSize[a_height]));function layoutItem(itemScene){var textSize=itemScene.labelTextSize();var hidden=!textSize||!textSize.width||!textSize.height;itemScene.isHidden=hidden;if(hidden){return}var widthMargin=0;var itemClientSize={width:textLeft+textSize.width+widthMargin,height:Math.max(textSize.height,markerDiam)};var isFirstInRow;if(!row){row=new pvc.visual.legend.BulletItemSceneRow(0);isFirstInRow=true}else{isFirstInRow=!row.items.length}var newRowWidth=row.size.width+itemClientSize[a_width];if(!isFirstInRow){newRowWidth+=itemPadding[a_width]}if(!isFirstInRow&&(newRowWidth>maxRowWidth)){commitRow(false);newRowWidth=itemClientSize[a_width]}var rowSize=row.size;rowSize.width=newRowWidth;rowSize.height=Math.max(rowSize.height,itemClientSize[a_height]);var rowItemIndex=row.items.length;row.items.push(itemScene);def.set(itemScene.vars,'row',row,'rowIndex',rowItemIndex,'clientSize',itemClientSize)}function commitRow(isLast){var rowSize=row.size;contentSize.height+=rowSize.height;if(rows.length){contentSize.height+=itemPadding[a_height]}contentSize.width=Math.max(contentSize.width,rowSize.width);rows.push(row);if(!isLast){row=new pvc.visual.legend.BulletItemSceneRow(rows.length)}}},defaultGroupSceneType:function(){var GroupType=this._bulletGroupType;if(!GroupType){GroupType=def.type(pvc.visual.legend.BulletGroupScene);this._bulletGroupType=GroupType}return GroupType},createGroup:function(keyArgs){var GroupType=this.defaultGroupSceneType();return new GroupType(this,keyArgs)}});def.type('pvc.visual.legend.BulletItemSceneRow').init(function(index){this.index=index;this.items=[];this.size={width:0,height:0}}); -def.type('pvc.visual.legend.BulletGroupScene',pvc.visual.Scene).init(function(rootScene,keyArgs){this.base(rootScene,keyArgs);this.extensionPrefix=def.get(keyArgs,'extensionPrefix')||'';this._renderer=def.get(keyArgs,'renderer');this.colorAxis=def.get(keyArgs,'colorAxis');this.clickMode=def.get(keyArgs,'clickMode');if(this.colorAxis&&!this.clickMode){this.clickMode=this.colorAxis.option('LegendClickMode')}}).add({hasRenderer:function(){return this._renderer},renderer:function(renderer){if(renderer!=null){this._renderer=renderer}else{renderer=this._renderer;if(!renderer){var keyArgs;var colorAxis=this.colorAxis;if(colorAxis){keyArgs={drawRule:colorAxis.option('LegendDrawLine'),drawMarker:colorAxis.option('LegendDrawMarker'),markerShape:colorAxis.option('LegendShape')}}renderer=new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs);this._renderer=renderer}}return renderer},itemSceneType:function(){var ItemType=this._itemSceneType;if(!ItemType){ItemType=def.type(pvc.visual.legend.BulletItemScene);var clickMode=this.clickMode;switch(clickMode){case'toggleSelected':ItemType.add(pvc.visual.legend.BulletItemSceneSelection);break;case'toggleVisible':ItemType.add(pvc.visual.legend.BulletItemSceneVisibility);break}this.panel()._extendSceneType('item',ItemType,['isOn','isClickable','click']);this._itemSceneType=ItemType}return ItemType},createItem:function(keyArgs){var ItemType=this.itemSceneType();return new ItemType(this,keyArgs)}}); -def.type('pvc.visual.legend.BulletItemScene',pvc.visual.Scene).init(function(bulletGroup,keyArgs){this.base(bulletGroup,keyArgs);var value,rawValue,label;if(keyArgs){value=keyArgs.value;rawValue=keyArgs.rawValue;label=keyArgs.label}if(value===undefined){var source=this.group||this.datum;if(source){value=source.value;rawValue=source.rawValue;label=source.ensureLabel();var dataPartDim=this.chart()._getDataPartDimName();if(dataPartDim){var dataPartAtom=source.atoms[dataPartDim];if(isNaN(+dataPartAtom.value)){label+=" ("+dataPartAtom.label+")"}}}}this.vars.value=new pvc.visual.ValueLabelVar(value||null,label||"",rawValue)}).add({isOn:function(){return true},isClickable:function(){return false},click:function(){},labelTextSize:function(){var valueVar=this.vars.value;return valueVar&&pv.Text.measure(valueVar.label,this.vars.font)}}); -def.type('pvc.visual.legend.BulletItemSceneSelection').add({isOn:function(){var owner=(this.group||this.datum).owner;return!owner.selectedCount()||this.datums().any(function(datum){return!datum.isNull&&datum.isSelected})},isClickable:function(){return this.chart()._canSelectWithClick()},click:function(){var datums=this.datums().array();if(datums.length){var chart=this.chart();chart._updatingSelections(function(){datums=chart._onUserSelection(datums);if(datums){var on=def.query(datums).any(function(datum){return datum.isSelected});pvc.data.Data.setSelected(datums,!on)}})}}}); -def.type('pvc.visual.legend.BulletItemSceneVisibility').add({isOn:function(){return this.datums().any(function(datum){return!datum.isNull&&datum.isVisible})},isClickable:function(){return true},click:function(){if(pvc.data.Data.toggleVisible(this.datums())){this.chart().render(true,true,false)}}}); -def.type('pvc.visual.legend.BulletItemRenderer'); -def.type('pvc.visual.legend.BulletItemDefaultRenderer',pvc.visual.legend.BulletItemRenderer).init(function(keyArgs){this.noSelect=def.get(keyArgs,'noSelect',false);this.noHover=def.get(keyArgs,'noHover',false);this.drawRule=def.get(keyArgs,'drawRule',false);if(this.drawRule){this.rulePvProto=def.get(keyArgs,'rulePvProto')}this.drawMarker=!this.drawRule||def.get(keyArgs,'drawMarker',true);if(this.drawMarker){this.markerShape=def.get(keyArgs,'markerShape','square');this.markerPvProto=def.get(keyArgs,'markerPvProto')}}).add({drawRule:false,drawMarker:true,markerShape:null,rulePvProto:null,markerPvProto:null,create:function(legendPanel,pvBulletPanel,extensionPrefix,wrapper){var renderInfo={};var drawRule=this.drawRule;var sceneColorProp=function(scene){return scene.color};if(drawRule){var rulePvBaseProto=new pv.Mark().left(0).top(function(){return this.parent.height()/2}).width(function(){return this.parent.width()}).lineWidth(1,pvc.extensionTag).strokeStyle(sceneColorProp,pvc.extensionTag);if(this.rulePvProto){rulePvBaseProto=this.rulePvProto.extend(rulePvBaseProto)}renderInfo.pvRule=new pvc.visual.Rule(legendPanel,pvBulletPanel,{proto:rulePvBaseProto,noSelect:this.noSelect,noHover:this.noHover,activeSeriesAware:false,extensionId:extensionPrefix+"Rule",wrapper:wrapper}).pvMark}if(this.drawMarker){var markerPvBaseProto=new pv.Mark().left(function(){return this.parent.width()/2}).top(function(){return this.parent.height()/2}).shapeSize(function(){return this.parent.width()},pvc.extensionTag).lineWidth(2,pvc.extensionTag).fillStyle(sceneColorProp,pvc.extensionTag).strokeStyle(sceneColorProp,pvc.extensionTag).shape(this.markerShape,pvc.extensionTag).angle(drawRule?0:Math.PI/2,pvc.extensionTag).antialias(function(){var cos=Math.abs(Math.cos(this.angle()));if(cos!==0&&cos!==1){switch(this.shape()){case'square':case'bar':return false}}return true},pvc.extensionTag);if(this.markerPvProto){markerPvBaseProto=this.markerPvProto.extend(markerPvBaseProto)}renderInfo.pvDot=new pvc.visual.Dot(legendPanel,pvBulletPanel,{proto:markerPvBaseProto,freePosition:true,activeSeriesAware:false,noTooltip:true,noSelect:this.noSelect,noHover:this.noHover,extensionId:extensionPrefix+"Dot",wrapper:wrapper}).pvMark}return renderInfo}}); -def.scope(function(){def.type('pvc.visual.Plot',pvc.visual.OptionsBase).init(function(chart,keyArgs){var typePlots=def.getPath(chart,['plotsByType',this.type]);var index=typePlots?typePlots.length:0;var globalIndex=chart.plotList.length;keyArgs=def.set(keyArgs,'byNaked',!globalIndex);this.base(chart,this.type,index,keyArgs);chart._addPlot(this);var prefixes=this.extensionPrefixes=[this.id];if(!this.globalIndex){prefixes.push('')}if(this.name){prefixes.push(this.name)}}).add({_getOptionsDefinition:function(){return pvc.visual.Plot.optionsDef},_resolveByNaked:pvc.options.specify(function(optionInfo){if(!this.globalIndex){return this._chartOption(def.firstLowerCase(optionInfo.name))}})});pvc.visual.Plot.optionsDef={Orientation:{resolve:function(optionInfo){optionInfo.specify(this._chartOption('orientation')||'vertical');return true},cast:String},ValuesVisible:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){if(this.globalIndex===0){var show=this._chartOption('showValues');if(show!==undefined){optionInfo.specify(show)}else{show=this.type!=='point';optionInfo.defaultValue(show)}return true}}},cast:Boolean,value:false},ValuesAnchor:{resolve:'_resolveFull',cast:pvc.parseAnchor},ValuesFont:{resolve:'_resolveFull',cast:String,value:'10px sans-serif'},ValuesMask:{resolve:'_resolveFull',cast:String,value:"{value}"},DataPart:{resolve:'_resolveFixed',cast:String,value:'0'},ColorRole:{resolve:'_resolveFixed',cast:String,value:'color'},ColorAxis:{resolve:pvc.options.resolvers([function(optionInfo){if(this.globalIndex===0){optionInfo.specify(1);return true}},'_resolveFull']),cast:function(value){value=pvc.castNumber(value);if(value!=null){value=def.between(value,1,10)}else{value=1}return value},value:1}}}); -def.scope(function(){def.type('pvc.visual.CartesianPlot',pvc.visual.Plot).add({_getOptionsDefinition:function(){return pvc.visual.CartesianPlot.optionsDef}});function castTrend(trend){if(this.name==='trend'){return null}var type=this.option('TrendType');if(!type&&trend){type=trend.type}if(!type||type==='none'){return null}if(!trend){trend={}}else{trend=Object.create(trend)}trend.type=type;var label=this.option('TrendLabel');if(label!==undefined){trend.label=label}return trend}pvc.visual.CartesianPlot.optionsDef=def.create(pvc.visual.Plot.optionsDef,{BaseAxis:{value:1},BaseRole:{resolve:'_resolveFixed',cast:String},OrthoAxis:{resolve:function(optionInfo){if(this.globalIndex===0){optionInfo.specify(1);return true}return this._resolveFull(optionInfo)},data:{resolveV1:function(optionInfo){if(this.name==='plot2'&&this.chart._allowV1SecondAxis&&this._chartOption('secondAxisIndependentScale')){optionInfo.specify(2)}return true}},cast:function(value){value=pvc.castNumber(value);if(value!=null){value=def.between(value,1,10)}else{value=1}return value},value:1},OrthoRole:{resolve:pvc.options.resolvers(['_resolveFixed','_resolveDefault'])},Trend:{resolve:'_resolveFull',data:{resolveDefault:function(optionInfo){var type=this.option('TrendType');if(type){optionInfo.defaultValue({type:type});return true}}},cast:castTrend},TrendType:{resolve:'_resolveFull',cast:pvc.parseTrendType},TrendLabel:{resolve:'_resolveFull',cast:String},NullInterpolationMode:{resolve:'_resolveFull',cast:pvc.parseNullInterpolationMode,value:'none'}})}); -def.scope(function(){def.type('pvc.visual.CategoricalPlot',pvc.visual.CartesianPlot).add({_getOptionsDefinition:function(){return pvc.visual.CategoricalPlot.optionsDef}});pvc.visual.CategoricalPlot.optionsDef=def.create(pvc.visual.CartesianPlot.optionsDef,{Stacked:{resolve:'_resolveFull',cast:Boolean,value:false},BaseRole:{value:'category'},OrthoRole:{value:'value'}})}); -def.scope(function(){def.type('pvc.visual.BarPlotAbstract',pvc.visual.CategoricalPlot).add({_getOptionsDefinition:function(){return pvc.visual.BarPlotAbstract.optionsDef}});pvc.visual.BarPlotAbstract.optionsDef=def.create(pvc.visual.CategoricalPlot.optionsDef,{BarSizeRatio:{resolve:'_resolveFull',cast:function(value){value=pvc.castNumber(value);if(value==null){value=1}else if(value<0.05){value=0.05}else if(value>1){value=1}return value},value:0.9},BarSizeMax:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyChartOption(optionInfo,'maxBarSize');return true}},cast:function(value){value=pvc.castNumber(value);if(value==null){value=Infinity}else if(value<1){value=1}return value},value:2000},BarStackedMargin:{resolve:'_resolveFull',cast:function(value){value=pvc.castNumber(value);if(value!=null&&value<0){value=0}return value},value:0},OverflowMarkersVisible:{resolve:'_resolveFull',cast:Boolean,value:true},ValuesAnchor:{value:'center'}})}); -def.type('pvc.visual.BarPlot',pvc.visual.BarPlotAbstract).add({type:'bar'}); -def.scope(function(){def.type('pvc.visual.NormalizedBarPlot',pvc.visual.BarPlotAbstract).add({type:'bar',_getOptionsDefinition:function(){return pvc.visual.NormalizedBarPlot.optionsDef}});pvc.visual.NormalizedBarPlot.optionsDef=def.create(pvc.visual.BarPlotAbstract.optionsDef,{Stacked:{resolve:null,value:true}})}); -def.scope(function(){def.type('pvc.visual.WaterfallPlot',pvc.visual.BarPlotAbstract).add({type:'water',_getOptionsDefinition:function(){return pvc.visual.WaterfallPlot.optionsDef}});pvc.visual.WaterfallPlot.optionsDef=def.create(pvc.visual.BarPlotAbstract.optionsDef,{Stacked:{resolve:null,value:true},TotalLineLabel:{resolve:'_resolveFull',cast:String,value:"Accumulated"},TotalValuesVisible:{resolve:'_resolveFull',data:{resolveDefault:function(optionInfo){optionInfo.defaultValue(this.option('ValuesVisible'));return true}},cast:Boolean},Direction:{resolve:'_resolveFull',cast:pvc.parseWaterDirection,value:'down'},AreasVisible:{resolve:'_resolveFull',cast:Boolean,value:true},AllCategoryLabel:{resolve:'_resolveFull',cast:String,value:"All"}})}); -def.scope(function(){def.type('pvc.visual.PointPlot',pvc.visual.CategoricalPlot).add({type:'point',_getOptionsDefinition:function(){return pvc.visual.PointPlot.optionsDef}});function visibleData(type,dv){return{resolveV1:function(optionInfo){if(this.globalIndex===0){if(!this._specifyChartOption(optionInfo,'show'+type)){optionInfo.defaultValue(dv)}return true}}}}pvc.visual.PointPlot.optionsDef=def.create(pvc.visual.CategoricalPlot.optionsDef,{DotsVisible:{resolve:'_resolveFull',data:visibleData('Dots',true),cast:Boolean,value:false},LinesVisible:{resolve:'_resolveFull',data:visibleData('Lines',true),cast:Boolean,value:false},AreasVisible:{resolve:'_resolveFull',data:visibleData('Areas',false),cast:Boolean,value:false},ValuesAnchor:{value:'right'}})}); -def.scope(function(){def.type('pvc.visual.MetricXYPlot',pvc.visual.CartesianPlot).add({_getOptionsDefinition:function(){return pvc.visual.MetricXYPlot.optionsDef}});pvc.visual.MetricXYPlot.optionsDef=def.create(pvc.visual.CartesianPlot.optionsDef,{BaseRole:{value:'x'},OrthoAxis:{resolve:null},OrthoRole:{value:'y'}})}); -def.scope(function(){def.type('pvc.visual.MetricPointPlot',pvc.visual.MetricXYPlot).add({type:'scatter',_getOptionsDefinition:function(){return pvc.visual.MetricPointPlot.optionsDef}});function visibleData(type){return{resolveV1:function(optionInfo){this._specifyChartOption(optionInfo,'show'+type);return true}}}pvc.visual.MetricPointPlot.optionsDef=def.create(pvc.visual.MetricXYPlot.optionsDef,{SizeRole:{resolve:'_resolveFixed',value:'size'},SizeAxis:{resolve:'_resolveFixed',value:1},Shape:{resolve:'_resolveFull',cast:pvc.parseShape,value:'circle'},DotsVisible:{resolve:'_resolveFull',data:visibleData('Dots'),cast:Boolean,value:false},LinesVisible:{resolve:'_resolveFull',data:visibleData('Lines'),cast:Boolean,value:false},ValuesAnchor:{value:'right'}})}); -def.scope(function(){def.type('pvc.visual.PiePlot',pvc.visual.Plot).add({type:'pie',_getOptionsDefinition:function(){return pvc.visual.PiePlot.optionsDef}});pvc.visual.PiePlot.optionsDef=def.create(pvc.visual.Plot.optionsDef,{ActiveSliceRadius:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:new pvc.PercentValue(0.05)},ExplodedSliceRadius:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:0},ExplodedSliceIndex:{resolve:'_resolveFull',cast:pvc.castNumber,value:null},ValuesAnchor:{cast:pvc.parseAnchorWedge,value:'outer'},ValuesVisible:{value:true},ValuesLabelStyle:{resolve:function(optionInfo){var isV1Compat=this.chart.compatVersion()<=1;if(isV1Compat){optionInfo.specify('inside');return true}return this._resolveFull(optionInfo)},cast:function(value){switch(value){case'inside':case'linked':return value}if(pvc.debug>=2){pvc.log("[Warning] Invalid 'ValuesLabelStyle' value: '"+value+"'.")}return'linked'},value:'linked'},ValuesMask:{resolve:'_resolveFull',data:{resolveDefault:function(optionInfo){optionInfo.defaultValue(this.option('ValuesLabelStyle')==='linked'?"{value} ({value.percent})":"{value}");return true}}},LinkInsetRadius:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:new pvc.PercentValue(0.05)},LinkOutsetRadius:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:new pvc.PercentValue(0.025)},LinkMargin:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:new pvc.PercentValue(0.025)},LinkHandleWidth:{resolve:'_resolveFull',cast:pvc.castNumber,value:0.5},LinkLabelSize:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:new pvc.PercentValue(0.15)},LinkLabelSpacingMin:{resolve:'_resolveFull',cast:pvc.castNumber,value:0.5}})}); -def.scope(function(){def.type('pvc.visual.HeatGridPlot',pvc.visual.CategoricalPlot).add({type:'heatGrid',_getOptionsDefinition:function(){return pvc.visual.HeatGridPlot.optionsDef}});pvc.visual.HeatGridPlot.optionsDef=def.create(pvc.visual.CategoricalPlot.optionsDef,{SizeRole:{value:'size'},SizeAxis:{value:1},UseShapes:{resolve:'_resolveFull',cast:Boolean,value:false},Shape:{resolve:'_resolveFull',cast:pvc.parseShape,value:'square'},NullShape:{resolve:'_resolveFull',cast:pvc.parseShape,value:'cross'},ValuesVisible:{value:true},OrthoRole:{value:'series'},OrthoAxis:{resolve:null},NullInterpolationMode:{resolve:null,value:'none'},Stacked:{resolve:null,value:false}})}); -def.scope(function(){def.type('pvc.visual.BoxPlot',pvc.visual.CategoricalPlot).add({type:'box',_getOptionsDefinition:function(){return pvc.visual.BoxPlot.optionsDef}});pvc.visual.BoxPlot.optionsDef=def.create(pvc.visual.CategoricalPlot.optionsDef,{Stacked:{resolve:null,value:false},OrthoRole:{value:['median','lowerQuartil','upperQuartil','minimum','maximum']},BoxSizeRatio:{resolve:'_resolveFull',cast:function(value){value=pvc.castNumber(value);if(value==null){value=1}else if(value<0.05){value=0.05}else if(value>1){value=1}return value},value:1/3},BoxSizeMax:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyChartOption(optionInfo,'maxBoxSize');return true}},cast:function(value){value=pvc.castNumber(value);if(value==null){value=Infinity}else if(value<1){value=1}return value},value:Infinity}})}); -def.type('pvc.visual.BulletPlot',pvc.visual.Plot).add({type:'bullet',_getOptionsDefinition:function(){return pvc.visual.BulletPlot.optionsDef}});pvc.visual.BulletPlot.optionsDef=def.create(pvc.visual.Plot.optionsDef,{ValuesVisible:{value:true},ColorRole:{value:null}}); -def.type('pvc.Abstract').init(function(){this._syncLog()}).add({invisibleLineWidth:0.001,defaultLineWidth:1.5,_logInstanceId:null,_syncLog:function(){if(pvc.debug&&typeof console!=="undefined"){var logId=this._getLogInstanceId();['log','info',['trace','debug'],'error','warn','group','groupEnd'].forEach(function(ps){ps=ps instanceof Array?ps:[ps,ps];pvc._installLog(this,'_'+ps[0],ps[1],logId)},this)}},_getLogInstanceId:function(){return this._logInstanceId||(this._logInstanceId=this._processLogInstanceId(this._createLogInstanceId()))},_createLogInstanceId:function(){return''+this.constructor},_processLogInstanceId:function(logInstanceId){var L=30;var s=logInstanceId.substr(0,L);if(s.length=3){this._info("NEW CHART\n"+pvc.logSeparator.replace(/-/g,'=')+"\n DebugLevel: "+pvc.debug)}if(pvc.debug>=3&&!parent&&originalOptions){this._info("OPTIONS:\n",originalOptions);if(pvc.debug>=5){this._trace(pvc.stringify(options,{ownOnly:false,funs:true}))}}if(parent){parent._addChild(this)}this._constructData(options);this._constructVisualRoles(options)}).add({_disposed:false,_animatable:false,parent:null,children:null,root:null,isPreRendered:false,_createVersion:0,renderCallback:undefined,multiChartPageCount:null,multiChartPageIndex:null,left:0,top:0,width:null,height:null,margins:null,paddings:null,_allowV1SecondAxis:false,compatVersion:function(options){return(options||this.options).compatVersion},_createLogInstanceId:function(){return""+this.constructor+this._createLogChildSuffix()},_createLogChildSuffix:function(){return this.parent?(" ("+(this.smallRowIndex+1)+","+(this.smallColIndex+1)+")"):""},_addChild:function(childChart){(childChart.parent===this)||def.assert("Not a child of this chart.");this.children.push(childChart)},_preRender:function(keyArgs){this._preRenderPhase1(keyArgs);this._preRenderPhase2(keyArgs)},_preRenderPhase1:function(keyArgs){this._createVersion++;this.isPreRendered=false;if(pvc.debug>=3){this._log("Prerendering")}this.children=[];if(!this.parent){pvc.removeTipsyLegends()}this._processOptions();this._checkNoDataI();if(!this.parent&&this._createVersion===1){this._initVisualRoles();this._bindVisualRolesPreI();this._complexTypeProj=this._createComplexTypeProject();this._bindVisualRolesPreII()}this._initData(keyArgs);this._checkNoDataII();var hasMultiRole=this._isRoleAssigned('multiChart');this._initPlots(hasMultiRole);this._initAxes(hasMultiRole);this._bindAxes(hasMultiRole);if(this.parent||!hasMultiRole){this._interpolate(hasMultiRole);this._generateTrends(hasMultiRole)}this._setAxesScales(hasMultiRole)},_preRenderPhase2:function(){var hasMultiRole=this._isRoleAssigned('multiChart');this._initChartPanels(hasMultiRole);this.isPreRendered=true},_setSmallLayout:function(keyArgs){if(keyArgs){var basePanel=this.basePanel;if(this._setProp('left',keyArgs)|this._setProp('top',keyArgs)){if(basePanel){def.set(basePanel.position,'left',this.left,'top',this.top)}}if(this._setProp('width',keyArgs)|this._setProp('height',keyArgs)){if(basePanel){basePanel.size=new pvc.Size(this.width,this.height)}}if(this._setProp('margins',keyArgs)&&basePanel){basePanel.margins=new pvc.Sides(this.margins)}if(this._setProp('paddings',keyArgs)&&basePanel){basePanel.paddings=new pvc.Sides(this.paddings)}}},_setProp:function(p,keyArgs){var v=keyArgs[p];if(v!=null){this[p]=v;return true}},_processOptions:function(){var options=this.options;if(parseInt(options.width,10)+"%"==options.width){try{var viewportwidth,viewportheight,wdiv,r,scr=null,inn=null,wNoScroll=0,wScroll=0;if(typeof window.innerWidth!='undefined'){viewportwidth=window.innerWidth,viewportheight=window.innerHeight}else if(typeof document.documentElement!='undefined'&&typeof document.documentElement.clientWidth!='undefined'&&document.documentElement.clientWidth!=0){viewportwidth=document.documentElement.clientWidth,viewportheight=document.documentElement.clientHeight}else{viewportwidth=document.getElementsByTagName('body')[0].clientWidth,viewportheight=document.getElementsByTagName('body')[0].clientHeight}scr=document.createElement('div');scr.style.position='absolute';scr.style.top='-1000px';scr.style.left='-1000px';scr.style.width='100px';scr.style.height='50px';scr.style.overflow='hidden';inn=document.createElement('div');inn.style.width='100%';inn.style.height='200px';scr.appendChild(inn);document.body.appendChild(scr);wNoScroll=inn.offsetWidth;scr.style.overflow='auto';wScroll=inn.offsetWidth;document.body.removeChild(document.body.lastChild);viewportwidth=viewportwidth-(wNoScroll-wScroll);r=(parseInt(options.width,10)/100)*viewportwidth;options.width=parseInt(r,10)}catch(e){options.width=parseInt(options.width,10)}}if(!this.parent){this.width=options.width;this.height=options.height;this.margins=options.margins;this.paddings=options.paddings}if(this.compatVersion()<=1){options.plot2=this._allowV1SecondAxis&&!!options.secondAxis}this._processOptionsCore(options);this._processExtensionPoints();return options},_processOptionsCore:function(options){if(!this.parent){if(!$.support.svg||pv.renderer()==='batik'){options.animate=false}this._processTooltipOptions(options)}},_tooltipDefaults:{gravity:'s',delayIn:200,delayOut:80,offset:2,opacity:0.9,html:true,fade:true,useCorners:false,arrowVisible:true,followMouse:false,format:undefined},_processTooltipOptions:function(options){var isV1Compat=this.compatVersion()<=1;var tipOptions=options.tooltip;var tipEnabled=options.tooltipEnabled;if(tipEnabled==null){if(tipOptions){tipEnabled=tipOptions.enabled}if(tipEnabled==null){if(isV1Compat){tipEnabled=options.showTooltips}if(tipEnabled==null){tipEnabled=true}}}if(tipEnabled){if(!tipOptions){tipOptions={}}if(isV1Compat){this._importV1TooltipOptions(tipOptions,options)}def.eachOwn(this._tooltipDefaults,function(dv,p){var value=options['tooltip'+def.firstUpperCase(p)];if(value!==undefined){tipOptions[p]=value}else if(tipOptions[p]===undefined){tipOptions[p]=dv}})}else{tipOptions={}}this._tooltipEnabled=tipEnabled;this._tooltipOptions=tipOptions},_importV1TooltipOptions:function(tipOptions,options){var v1TipOptions=options.tipsySettings;if(v1TipOptions){this.extend(v1TipOptions,"tooltip");for(var p in v1TipOptions){if(tipOptions[p]===undefined){tipOptions[p]=v1TipOptions[p]}}if(tipOptions.html==null){tipOptions.html=false}}},render:function(bypassAnimation,recreate,reloadData){var hasError;if(pvc.debug>1){pvc.group("CCC RENDER")}this._suspendSelectionUpdate();try{this.useTextMeasureCache(function(){try{if(!this.isPreRendered||recreate){this._preRender({reloadData:reloadData})}else if(!this.parent&&this.isPreRendered){pvc.removeTipsyLegends()}this.basePanel.render({bypassAnimation:bypassAnimation,recreate:recreate})}catch(e){if(e instanceof NoDataException){if(pvc.debug>1){this._log("No data found.")}this._addErrorPanelMessage("No data found",true)}else{hasError=true;pvc.logError(e.message);if(pvc.debug>0){this._addErrorPanelMessage("Error: "+e.message,false)}}}})}finally{if(!hasError){this._resumeSelectionUpdate()}if(pvc.debug>1){pvc.groupEnd()}}return this},_addErrorPanelMessage:function(text,isNoData){var options=this.options,pvPanel=new pv.Panel().canvas(options.canvas).width(this.width).height(this.height),pvMsg=pvPanel.anchor("center").add(pv.Label).text(text);if(isNoData){this.extend(pvMsg,"noDataMessage")}pvPanel.render()},useTextMeasureCache:function(fun,ctx){var root=this.root;var textMeasureCache=root._textMeasureCache||(root._textMeasureCache=pv.Text.createCache());return pv.Text.usingCache(textMeasureCache,fun,ctx||this)},animate:function(start,end){return this.basePanel.animate(start,end)},isAnimatingStart:function(){return this.basePanel.isAnimatingStart()},isOrientationVertical:function(orientation){return(orientation||this.options.orientation)===pvc.orientation.vertical},isOrientationHorizontal:function(orientation){return(orientation||this.options.orientation)===pvc.orientation.horizontal},dispose:function(){if(!this._disposed){this._disposed=true}},defaults:{width:400,height:300,orientation:'vertical',ignoreNulls:true,crosstabMode:true,isMultiValued:false,seriesInRows:false,groupedLabelSep:undefined,animate:true,titlePosition:"top",titleAlign:"center",legend:false,legendPosition:"bottom",v1StyleTooltipFormat:function(s,c,v,datum){return s+", "+c+": "+this.chart.options.valueFormat(v)+(datum&&datum.percent?(" ("+datum.percent.label+")"):"")},valueFormat:def.scope(function(){var pvFormat=pv.Format.number().fractionDigits(0,2);return function(d){return pvFormat.format(d)}}),percentValueFormat:def.scope(function(){var pvFormat=pv.Format.number().fractionDigits(0,1);return function(d){return pvFormat.format(d*100)+"%"}}),clickable:false,doubleClickMaxDelay:300,hoverable:false,selectable:false,selectionMode:'rubberband',ctrlSelectMode:true,clearSelectionMode:'emptySpaceClick',compatVersion:Infinity}}); -pvc.BaseChart.add({_visualRoles:null,_visualRoleList:null,_serRole:null,_dataPartRole:null,_measureVisualRoles:null,_constructVisualRoles:function(){var parent=this.parent;if(parent){this._visualRoles=parent._visualRoles;this._visualRoleList=parent._visualRoleList;this._measureVisualRoles=parent._measureVisualRoles;if(parent._multiChartRole){this._multiChartRole=parent._multiChartRole}if(parent._serRole){this._serRole=parent._serRole}if(parent._colorRole){this._colorRole=parent._colorRole}if(parent._dataPartRole){this._dataPartRole=parent._dataPartRole}}else{this._visualRoles={};this._visualRoleList=[];this._measureVisualRoles=[]}},_hasDataPartRole:function(){return false},_getSeriesRoleSpec:function(){return null},_getColorRoleSpec:function(){return null},_addVisualRole:function(name,keyArgs){keyArgs=def.set(keyArgs,'index',this._visualRoleList.length);var visualRole=new pvc.visual.Role(name,keyArgs);this._visualRoleList.push(visualRole);this._visualRoles[name]=visualRole;if(visualRole.isMeasure){this._measureVisualRoles.push(visualRole)}return visualRole},_initVisualRoles:function(){this._multiChartRole=this._addVisualRole('multiChart',{defaultDimension:'multiChart*',requireIsDiscrete:true});if(this._hasDataPartRole()){this._dataPartRole=this._addVisualRole('dataPart',{defaultDimension:'dataPart',requireSingleDimension:true,requireIsDiscrete:true,dimensionDefaults:{isHidden:true,comparer:def.compare}})}var serRoleSpec=this._getSeriesRoleSpec();if(serRoleSpec){this._serRole=this._addVisualRole('series',serRoleSpec)}var colorRoleSpec=this._getColorRoleSpec();if(colorRoleSpec){this._colorRole=this._addVisualRole('color',colorRoleSpec)}},_bindVisualRolesPreI:function(){def.eachOwn(this._visualRoles,function(role){role.setIsReversed(false)});var sourcedRoles=[];var options=this.options;var roleOptions=options.visualRoles;this._visualRoleList.forEach(function(visualRole){var name=visualRole.name;var roleSpec=options[name+'Role'];if(roleSpec!==undefined){if(!roleOptions){roleOptions=options.visualRoles={}}if(roleOptions[name]===undefined){roleOptions[name]=roleSpec}}});var dimsBoundToSingleRole;if(roleOptions){dimsBoundToSingleRole={};var rolesWithOptions=def.query(def.keys(roleOptions)).select(function(name){return this._visualRoles[name]||def.fail.operationInvalid("Role '{0}' is not supported by the chart type.",[name])},this).array();rolesWithOptions.sort(function(a,b){return a.index-b.index});rolesWithOptions.forEach(function(visualRole){var name=visualRole.name;var roleSpec=roleOptions[name];var groupingSpec,sourceRoleName;if(def.object.is(roleSpec)){if(def.nullyTo(roleSpec.isReversed,false)){visualRole.setIsReversed(true)}sourceRoleName=roleSpec.from;if(sourceRoleName&&(sourceRoleName!==name)){var sourceRole=this._visualRoles[sourceRoleName]||def.fail.operationInvalid("Source role '{0}' is not supported by the chart type.",[sourceRoleName]);visualRole.setSourceRole(sourceRole);sourcedRoles.push(visualRole)}else{groupingSpec=roleSpec.dimensions}}else{groupingSpec=roleSpec}if(groupingSpec!==undefined){var grouping=pvc.data.GroupingSpec.parse(groupingSpec);visualRole.preBind(grouping);grouping.dimensions().each(function(groupDimSpec){if(def.hasOwn(dimsBoundToSingleRole,groupDimSpec.name)){delete dimsBoundToSingleRole[groupDimSpec.name]}else{dimsBoundToSingleRole[groupDimSpec.name]=visualRole}})}},this)}this._sourcedRoles=sourcedRoles;this._dimsBoundToSingleRole=dimsBoundToSingleRole},_bindVisualRolesPreII:function(){var dimsBoundToSingleRole=this._dimsBoundToSingleRole;if(dimsBoundToSingleRole){delete this._dimsBoundToSingleRole;def.eachOwn(dimsBoundToSingleRole,this._setRoleBoundDimensionDefaults,this)}var sourcedRoles=this._sourcedRoles;delete this._sourcedRoles;def.query(this._visualRoleList).where(function(role){return role.defaultSourceRoleName&&!role.sourceRole&&!role.isPreBound()}).each(function(role){var sourceRole=this._visualRoles[role.defaultSourceRoleName];if(sourceRole){role.setSourceRole(sourceRole);sourcedRoles.push(role)}},this);sourcedRoles.forEach(function(role){var sourceRole=role.sourceRole;if(sourceRole.isReversed){role.setIsReversed(!role.isReversed)}if(!role.defaultDimensionName&&sourceRole.isPreBound()){role.preBind(sourceRole.preBoundGrouping())}})},_setRoleBoundDimensionDefaults:function(role,dimName){this._complexTypeProj.setDimDefaults(dimName,role.dimensionDefaults)},_bindVisualRolesPostI:function(){var complexTypeProj=this._complexTypeProj;var boundDimTypes={};var unboundSourcedRoles=[];def.query(this._visualRoleList).where(function(role){return role.isPreBound()}).each(markPreBoundRoleDims,this);def.query(this._visualRoleList).where(function(role){return!role.isPreBound()}).each(autoBindUnboundRole,this);unboundSourcedRoles.forEach(tryPreBindSourcedRole,this);def.query(def.ownKeys(boundDimTypes)).where(function(dimName){return boundDimTypes[dimName].length===1}).each(function(dimName){var singleRole=boundDimTypes[dimName][0];this._setRoleBoundDimensionDefaults(singleRole,dimName)},this);function markDimBoundTo(dimName,role){def.array.lazy(boundDimTypes,dimName).push(role)}function dimIsDefined(dimName){return complexTypeProj.hasDim(dimName)}function preBindRoleTo(role,dimNames){if(def.array.is(dimNames)){dimNames.forEach(function(dimName){markDimBoundTo(dimName,role)})}else{markDimBoundTo(dimNames,role)}role.setSourceRole(null);role.preBind(pvc.data.GroupingSpec.parse(dimNames))}function preBindRoleToGroupDims(role,groupDimNames){if(groupDimNames.length){if(role.requireSingleDimension){preBindRoleTo(role,groupDimNames[0])}else{preBindRoleTo(role,groupDimNames)}}}function preBindRoleToNewDim(role,dimName){complexTypeProj.setDim(dimName,{isHidden:true});preBindRoleTo(role,dimName)}function roleIsUnbound(role){if(role.isRequired){throw def.error.operationInvalid("Chart type requires unassigned role '{0}'.",[role.name])}role.bind(null);role.setSourceRole(null)}function markPreBoundRoleDims(role){role.preBoundGrouping().dimensionNames().forEach(markDimBoundTo)}function autoBindUnboundRole(role){var name=role.name;var dimName=role.defaultDimensionName;if(!dimName){if(role.sourceRole){unboundSourcedRoles.push(role)}else{roleIsUnbound(role)}return}var match=dimName.match(/^(.*?)(\*)?$/)||def.fail.argumentInvalid('defaultDimensionName');var defaultName=match[1];var greedy=match[2];if(greedy){var groupDimNames=complexTypeProj.groupDimensionsNames(defaultName);if(groupDimNames){preBindRoleToGroupDims(role,groupDimNames);return}}else if(dimIsDefined(defaultName)){preBindRoleTo(role,defaultName);return}if(role.autoCreateDimension){preBindRoleToNewDim(role,defaultName);return}if(role.sourceRole){unboundSourcedRoles.push(role)}else{roleIsUnbound(role)}}function tryPreBindSourcedRole(role){var sourceRole=role.sourceRole;if(sourceRole.isPreBound()){role.preBind(sourceRole.preBoundGrouping())}else{roleIsUnbound(role)}}},_bindVisualRolesPostII:function(complexType){def.query(this._visualRoleList).where(function(role){return role.isPreBound()}).each(commitRolePreBinding,this);function commitRolePreBinding(role){role.postBind(complexType)}},_logVisualRoles:function(){var out=["VISUAL ROLES MAP SUMMARY",pvc.logSeparator," VisualRole <-- Dimensions",pvc.logSeparator];def.eachOwn(this._visualRoles,function(role,name){out.push(" "+name+def.array.create(18-name.length," ").join("")+(role.grouping?(" <-- "+role.grouping):''))});this._log(out.join("\n"))},visualRoles:function(roleName,keyArgs){if(roleName==null){return def.own(this._visualRoles)}var role=def.getOwn(this._visualRoles,roleName)||null;if(!role&&def.get(keyArgs,'assertExists',true)){throw def.error.argumentInvalid('roleName',"Undefined role name '{0}'.",[roleName])}return role},measureVisualRoles:function(){return this._measureVisualRoles},measureDimensionsNames:function(){return def.query(this._measureVisualRoles).select(function(visualRole){return visualRole.firstDimensionName()}).where(def.notNully).array()},_isRoleAssigned:function(roleName){return!!this._visualRoles[roleName].grouping},_getDataPartDimName:function(){var role=this._dataPartRole;if(role){if(role.isBound()){return role.firstDimensionName()}var preGrouping=role.preBoundGrouping();if(preGrouping){return preGrouping.firstDimensionName()}return role.defaultDimensionName}}}); -pvc.BaseChart.add({dataEngine:null,data:null,_partData:null,_visibleDataCache:null,resultset:[],metadata:[],_constructData:function(options){var parent=this.parent;if(parent){this.dataEngine=this.data=options.data||def.fail.argumentRequired('options.data')}},_checkNoDataI:function(){if(!this.parent){if(!this.allowNoData&&this.resultset.length===0){throw new NoDataException()}}},_checkNoDataII:function(){if(!this.parent){if(!this.allowNoData&&(!this.data||!this.data.count())){throw new NoDataException()}}},_initData:function(keyArgs){if(!this.parent){var data=this.data;if(!data||def.get(keyArgs,'reloadData',true)){this._onLoadData()}else{data.clearVirtuals();data.disposeChildren()}}delete this._partData;delete this._visibleDataCache;if(pvc.debug>=3){this._log(this.data.getInfo())}},_onLoadData:function(){var data=this.data;var options=this.options;var dataPartDimName=this._getDataPartDimName();var complexTypeProj=this._complexTypeProj;var translOptions=this._createTranslationOptions(dataPartDimName);var translation=this._createTranslation(translOptions);if(pvc.debug>=3){translation.logSource()}if(!data){translation.configureType();if(dataPartDimName&&!complexTypeProj.isReadOrCalc(dataPartDimName)){this._addDefaultDataPartCalculation(dataPartDimName)}}this._bindVisualRolesPostI();var complexType;if(!data){complexType=new pvc.data.ComplexType();complexTypeProj.configureComplexType(complexType,translOptions)}else{complexType=data.type}this._bindVisualRolesPostII(complexType);if(pvc.debug>=10){this._log(complexType.describe())}if(pvc.debug>=3){this._logVisualRoles()}if(!data){data=this.dataEngine=this.data=new pvc.data.Data({type:complexType,labelSep:options.groupedLabelSep})}var loadKeyArgs={where:this._getLoadFilter(),isNull:this._getIsNullDatum()};var resultQuery=translation.execute(data);data.load(resultQuery,loadKeyArgs)},_createComplexTypeProject:function(){var options=this.options;var complexTypeProj=new pvc.data.ComplexTypeProject(options.dimensionGroups);var userDimsSpec=options.dimensions;for(var dimName in userDimsSpec){complexTypeProj.setDim(dimName,userDimsSpec[dimName])}var dataPartDimName=this._getDataPartDimName();if(dataPartDimName){complexTypeProj.setDim(dataPartDimName);this._addPlot2SeriesDataPartCalculation(complexTypeProj,dataPartDimName)}var calcSpecs=options.calculations;if(calcSpecs){calcSpecs.forEach(function(calcSpec){complexTypeProj.setCalc(calcSpec)})}return complexTypeProj},_getLoadFilter:function(){if(this.options.ignoreNulls){var me=this;return function(datum){var isNull=datum.isNull;if(isNull&&pvc.debug>=4){me._info("Datum excluded.")}return!isNull}}},_getIsNullDatum:function(){var measureDimNames=this.measureDimensionsNames(),M=measureDimNames.length;if(M){return function(datum){var atoms=datum.atoms;for(var i=0;i1){return this._partData.where([def.set({},dataPartDimName,dataPartValues)])}dataPartValues=dataPartValues[0]}var child=this._partData._childrenByKey[dataPartValues+''];if(!child){var dataPartCell={v:dataPartValues};if(dataPartValues==='trend'){var firstTrendAtom=this._firstTrendAtomProto;if(firstTrendAtom){dataPartCell.f=firstTrendAtom.f}}child=new pvc.data.Data({parent:this._partData,atoms:def.set({},dataPartDimName,dataPartCell),dimNames:[dataPartDimName],datums:[]})}return child},visibleData:function(dataPartValue,keyArgs){var ignoreNulls=def.get(keyArgs,'ignoreNulls',true);if(ignoreNulls&&this.options.ignoreNulls){ignoreNulls=false}keyArgs=keyArgs?Object.create(keyArgs):{};keyArgs.ignoreNulls=ignoreNulls;var key=ignoreNulls+'|'+dataPartValue,data=def.getOwn(this._visibleDataCache,key);if(!data){data=this._createVisibleData(dataPartValue,keyArgs);if(data){(this._visibleDataCache||(this._visibleDataCache={}))[key]=data}}return data},_createVisibleData:function(dataPartValue,keyArgs){var partData=this.partData(dataPartValue);if(!partData){return null}var ignoreNulls=def.get(keyArgs,'ignoreNulls');return this._serRole&&this._serRole.grouping?partData.flattenBy(this._serRole,{visible:true,isNull:ignoreNulls?false:null}):partData},_generateTrends:function(){if(this._dataPartRole){def.query(def.own(this.axes)).selectMany(function(axis){return axis.dataCells}).where(function(dataCell){return!!dataCell.trend}).distinct(function(dataCell){return dataCell.role.name+'|'+(dataCell.dataPartValue||'')}).each(this._generateTrendsDataCell,this)}},_interpolate:function(){def.query(def.own(this.axes)).selectMany(function(axis){return axis.dataCells}).where(function(dataCell){var nim=dataCell.nullInterpolationMode;return!!nim&&nim!=='none'}).distinct(function(dataCell){return dataCell.role.name+'|'+(dataCell.dataPartValue||'')}).each(this._interpolateDataCell,this)},_interpolateDataCell:function(dataCell){},_generateTrendsDataCell:function(dataCell){},setData:function(data,options){this.setResultset(data.resultset);this.setMetadata(data.metadata);$.extend(this.options,options);return this},setResultset:function(resultset){!this.parent||def.fail.operationInvalid("Can only set resultset on root chart.");this.resultset=resultset;if(!resultset.length){this._log("Warning: Resultset is empty")}return this},setMetadata:function(metadata){!this.parent||def.fail.operationInvalid("Can only set resultset on root chart.");this.metadata=metadata;if(!metadata.length){this._log("Warning: Metadata is empty")}return this}}); -pvc.BaseChart.add({_initPlots:function(hasMultiRole){this.plotPanelList=null;if(!this.parent){this.plots={};this.plotList=[];this.plotsByType={};this._initPlotsCore(hasMultiRole)}else{var root=this.root;this.plots=root.plots;this.plotList=root.plotList;this.plotsByType=root.plotsByType}},_initPlotsCore:function(){},_addPlot:function(plot){var plotsByType=this.plotsByType;var plots=this.plots;var plotType=plot.type;var plotIndex=plot.index;var plotName=plot.name;var plotId=plot.id;if(plotName&&def.hasOwn(plots,plotName)){throw def.error.operationInvalid("Plot name '{0}' already taken.",[plotName])}if(def.hasOwn(plots,plotId)){throw def.error.operationInvalid("Plot id '{0}' already taken.",[plotId])}var typePlots=def.array.lazy(plotsByType,plotType);if(def.hasOwn(typePlots,plotIndex)){throw def.error.operationInvalid("Plot index '{0}' of type '{1}' already taken.",[plotIndex,plotType])}plot.globalIndex=this.plotList.length;typePlots[plotIndex]=plot;this.plotList.push(plot);plots[plotId]=plot;if(plotName){plots[plotName]=plot}},_collectPlotAxesDataCells:function(plot,dataCellsByAxisTypeThenIndex){var colorRoleName=plot.option('ColorRole');if(colorRoleName){var colorRole=this.visualRoles(colorRoleName);if(colorRole.isBound()){var colorDataCellsByAxisIndex=def.array.lazy(dataCellsByAxisTypeThenIndex,'color');def.array.lazy(colorDataCellsByAxisIndex,plot.option('ColorAxis')-1).push({plot:plot,role:colorRole,dataPartValue:plot.option('DataPart')})}}},_addPlotPanel:function(plotPanel){def.lazy(this,'plotPanels')[plotPanel.plot.id]=plotPanel;def.array.lazy(this,'plotPanelList').push(plotPanel)},_createPlotPanels:function(){throw def.error.notImplemented()}}); -pvc.BaseChart.add({colors:null,axes:null,axesList:null,axesByType:null,_axisClassByType:{'color':pvc.visual.ColorAxis,'size':pvc.visual.SizeAxis,'base':pvc.visual.CartesianAxis,'ortho':pvc.visual.CartesianAxis},_axisCreateWhere:{'color':1,'size':2,'base':3,'ortho':3},_axisCreationOrder:['color','size','base','ortho'],_axisCreateIfUnbound:{},_initAxes:function(hasMultiRole){this.axes={};this.axesList=[];this.axesByType={};delete this._rolesColorScale;var dataCellsByAxisTypeThenIndex;if(!this.parent){dataCellsByAxisTypeThenIndex={};this.plotList.forEach(function(plot){this._collectPlotAxesDataCells(plot,dataCellsByAxisTypeThenIndex)},this);this._fixTrendsLabel(dataCellsByAxisTypeThenIndex)}else{dataCellsByAxisTypeThenIndex=this.root._dataCellsByAxisTypeThenIndex}this._dataCellsByAxisTypeThenIndex=dataCellsByAxisTypeThenIndex;var here=0;if(!this.parent){here|=1}if(this.parent||!hasMultiRole){here|=2}this._axisCreateHere=here;this._axisCreationOrder.forEach(function(type){if((this._axisCreateWhere[type]&here)!==0){var AxisClass;var dataCellsByAxisIndex=dataCellsByAxisTypeThenIndex[type];if(dataCellsByAxisIndex){AxisClass=this._axisClassByType[type];if(AxisClass){dataCellsByAxisIndex.forEach(function(dataCells,axisIndex){new AxisClass(this,type,axisIndex)},this)}}else if(this._axisCreateIfUnbound[type]){AxisClass=this._axisClassByType[type];if(AxisClass){new AxisClass(this,type,0)}}}},this);if(this.parent){this.root.axesList.forEach(function(axis){if(!def.hasOwn(this.axes,axis.id)){this._addAxis(axis)}},this)}},_fixTrendsLabel:function(dataCellsByAxisTypeThenIndex){var dataPartDimName=this._getDataPartDimName();if(dataPartDimName){var firstDataCell=def.query(def.ownKeys(dataCellsByAxisTypeThenIndex)).selectMany(function(axisType){return dataCellsByAxisTypeThenIndex[axisType]}).selectMany().first(function(dataCell){return!!dataCell.trend});if(firstDataCell){var trendInfo=pvc.trends.get(firstDataCell.trend.type);var dataPartAtom=trendInfo.dataPartAtom;var trendLabel=firstDataCell.trend.label;if(trendLabel===undefined){trendLabel=dataPartAtom.f}this._firstTrendAtomProto={v:dataPartAtom.v,f:trendLabel}}else{delete this._firstTrendAtomProto}}},_addAxis:function(axis){this.axes[axis.id]=axis;if(axis.chart===this){axis.axisIndex=this.axesList.length}this.axesList.push(axis);var typeAxes=def.array.lazy(this.axesByType,axis.type);var typeIndex=typeAxes.count||0;axis.typeIndex=typeIndex;typeAxes[axis.index]=axis;if(!typeIndex){typeAxes.first=axis}typeAxes.count=typeIndex+1;if(axis.type==='color'&&axis.isBound()){this._onColorAxisScaleSet(axis)}return this},_getAxis:function(type,index){var typeAxes=this.axesByType[type];if(typeAxes&&index!=null&&(+index>=0)){return typeAxes[index]}},_bindAxes:function(){var here=this._axisCreateHere;def.eachOwn(this._dataCellsByAxisTypeThenIndex,function(dataCellsByAxisIndex,type){if((this._axisCreateWhere[type]&here)!==0){dataCellsByAxisIndex.forEach(function(dataCells,index){var axisId=pvc.buildIndexedId(type,index);var axis=this.axes[axisId];if(!axis.isBound()){axis.bind(dataCells)}},this)}},this)},_setAxesScales:function(){if(!this.parent){var colorAxes=this.axesByType.color;if(colorAxes){colorAxes.forEach(function(axis){if(axis.isBound()){axis.calculateScale();this._onColorAxisScaleSet(axis)}},this)}}},_onColorAxisScaleSet:function(axis){switch(axis.index){case 0:this.colors=axis.scheme();break;case 1:if(this._allowV1SecondAxis){this.secondAxisColor=axis.scheme()}break}},_getRoleColorScale:function(roleName){return def.lazy(def.lazy(this,'_rolesColorScale'),roleName,this._createRoleColorScale,this)},_createRoleColorScale:function(roleName){var firstScale,scale;var valueToColorMap={};this.axesByType.color.forEach(function(axis){var axisRole=axis.role;var isRoleCompatible=(axisRole.name===roleName)||(axisRole.sourceRole&&axisRole.sourceRole.name===roleName);if(isRoleCompatible&&axis.scale&&(axis.index===0||axis.option.isSpecified('Colors')||axis.option.isSpecified('Map'))){scale=axis.scale;if(!firstScale){firstScale=scale}axis.domainValues.forEach(addDomainValue)}},this);function addDomainValue(value){var key=''+value;if(!def.hasOwnProp.call(valueToColorMap,key)){valueToColorMap[key]=scale(value)}}if(!firstScale){return pvc.createColorScheme()()}scale=function(value){var key=''+value;if(def.hasOwnProp.call(valueToColorMap,key)){return valueToColorMap[key]}var color=firstScale(value);valueToColorMap[key]=color;return color};def.copy(scale,firstScale);return scale},_onLaidOut:function(){}}); -pvc.BaseChart.add({basePanel:null,titlePanel:null,legendPanel:null,_multiChartPanel:null,_initChartPanels:function(hasMultiRole){this._initBasePanel();this._initTitlePanel();var legendPanel=this._initLegendPanel();if(!this.parent&&hasMultiRole){this._initMultiChartPanel();if(legendPanel){this._initLegendScenes(legendPanel)}}else{var options=this.options;if(legendPanel){this._initLegendScenes(legendPanel)}this._preRenderContent({margins:hasMultiRole?options.smallContentMargins:options.contentMargins,paddings:hasMultiRole?options.smallContentPaddings:options.contentPaddings,clickAction:options.clickAction,doubleClickAction:options.doubleClickAction})}},_preRenderContent:function(contentOptions){},_initBasePanel:function(){var options=this.options;var basePanelParent=this.parent&&this.parent._multiChartPanel;this.basePanel=new pvc.BasePanel(this,basePanelParent,{margins:this.margins,paddings:this.paddings,size:{width:this.width,height:this.height}})},_initTitlePanel:function(){var options=this.options;if(!def.empty(options.title)){var isRoot=!this.parent;this.titlePanel=new pvc.TitlePanel(this,this.basePanel,{title:options.title,font:options.titleFont,anchor:options.titlePosition,align:options.titleAlign,alignTo:options.titleAlignTo,offset:options.titleOffset,keepInBounds:options.titleKeepInBounds,margins:options.titleMargins,paddings:options.titlePaddings,titleSize:options.titleSize,titleSizeMax:options.titleSizeMax})}},_initLegendPanel:function(){var options=this.options;if(options.legend){var legend=new pvc.visual.Legend(this,'legend',0);this.legendPanel=new pvc.LegendPanel(this,this.basePanel,{anchor:legend.option('Position'),align:legend.option('Align'),alignTo:options.legendAlignTo,offset:options.legendOffset,keepInBounds:options.legendKeepInBounds,size:legend.option('Size'),sizeMax:legend.option('SizeMax'),margins:legend.option('Margins'),paddings:legend.option('Paddings'),font:legend.option('Font'),scenes:def.getPath(options,'legend.scenes'),textMargin:options.legendTextMargin,itemPadding:options.legendItemPadding,markerSize:options.legendMarkerSize});return this.legendPanel}},_getLegendBulletRootScene:function(){return this.legendPanel&&this.legendPanel._getBulletRootScene()},_initMultiChartPanel:function(){var basePanel=this.basePanel;var options=this.options;this._multiChartPanel=new pvc.MultiChartPanel(this,basePanel,{margins:options.contentMargins,paddings:options.contentPaddings});this._multiChartPanel.createSmallCharts();basePanel._children.unshift(basePanel._children.pop())},_coordinateSmallChartsLayout:function(scopesByType){},_initLegendScenes:function(legendPanel){var rootScene,dataPartDimName;var legendIndex=0;var colorAxes=this.axesByType.color;if(colorAxes){colorAxes.forEach(processAxis,this)}function processAxis(colorAxis){if(colorAxis.option('LegendVisible')){var dataCells=colorAxis&&colorAxis.dataCells;if(dataCells){dataCells.forEach(function(dataCell){if(dataCell.role.isDiscrete()){var domainData=dataCell.data;if(!rootScene){dataPartDimName=this._getDataPartDimName();rootScene=legendPanel._getBulletRootScene()}var dataPartAtom;var locked=colorAxis.option('LegendClickMode')==='toggleVisible'&&(dataPartAtom=domainData.atoms[dataPartDimName])&&dataPartAtom.value==='trend';var groupScene=rootScene.createGroup({group:domainData,colorAxis:colorAxis,clickMode:locked?'none':undefined,extensionPrefix:pvc.buildIndexedId('',legendIndex++)});dataCell.legendBulletGroupScene=groupScene;var partColorScale=colorAxis.scale;domainData.children().each(function(itemData){var itemScene=groupScene.createItem({group:itemData});itemScene.color=partColorScale(itemData.value)})}},this)}}}}}); -pvc.BaseChart.add({_updateSelectionSuspendCount:0,_lastSelectedDatums:null,clearSelections:function(){if(this.data.owner.clearSelected()){this.updateSelections()}return this},_updatingSelections:function(method,context){this._suspendSelectionUpdate();try{method.call(context||this)}finally{this._resumeSelectionUpdate()}},_suspendSelectionUpdate:function(){if(this===this.root){this._updateSelectionSuspendCount++}else{this.root._suspendSelectionUpdate()}},_resumeSelectionUpdate:function(){if(this===this.root){if(this._updateSelectionSuspendCount>0){if(!(--this._updateSelectionSuspendCount)){this.updateSelections()}}}else{this.root._resumeSelectionUpdate()}},updateSelections:function(keyArgs){if(this===this.root){if(this._inUpdateSelections){return this}if(this._updateSelectionSuspendCount){return this}var selectedChangedDatumMap=this._calcSelectedChangedDatums();if(!selectedChangedDatumMap){return}pvc.removeTipsyLegends();this._inUpdateSelections=true;try{var action=this.options.selectionChangedAction;if(action){var selectedDatums=this.data.selectedDatums();var selectedChangedDatums=selectedChangedDatumMap.values();action.call(this.basePanel._getContext(),selectedDatums,selectedChangedDatums)}if(def.get(keyArgs,'render',true)){this.useTextMeasureCache(function(){this.basePanel.renderInteractive()},this)}}finally{this._inUpdateSelections=false}}else{this.root.updateSelections()}return this},_calcSelectedChangedDatums:function(){var selectedChangedDatums;var nowSelectedDatums=this.data.selectedDatumMap();var lastSelectedDatums=this._lastSelectedDatums;if(!lastSelectedDatums){if(!nowSelectedDatums.count){return}selectedChangedDatums=nowSelectedDatums.clone()}else{selectedChangedDatums=lastSelectedDatums.symmetricDifference(nowSelectedDatums);if(!selectedChangedDatums.count){return}}this._lastSelectedDatums=nowSelectedDatums;var datums=this._lastSelectedDatums?this._lastSelectedDatums.values():[];return selectedChangedDatums},_onUserSelection:function(datums){if(!datums||!datums.length){return datums}if(this===this.root){var action=this.options.userSelectionAction;if(action){return action.call(null,datums)||datums}return datums}return this.root._onUserSelection(datums)},_isSelectable:function(){return this.options.selectable},_canSelectWithRubberband:function(){var options=this.options;return options.selectable&&options.selectionMode==='rubberband'},_canSelectWithClick:function(){return this._canSelectWithRubberband()},_canSelectWithFocusWindow:function(){var options=this.options;return options.selectable&&options.selectionMode==='focuswindow'}}); -pvc.BaseChart.add({_processExtensionPoints:function(){var components;if(!this.parent){var points=this.options.extensionPoints;components={};if(points){for(var p in points){var id,prop;var splitIndex=p.indexOf("_");if(splitIndex>0){id=p.substring(0,splitIndex);prop=p.substr(splitIndex+1);if(id&&prop){var component=def.getOwn(components,id)||(components[id]=new def.OrderedMap());component.add(prop,points[p])}}}}}else{components=this.parent._components}this._components=components},extend:function(mark,ids,keyArgs){if(def.array.is(ids)){ids.forEach(function(id){this._extendCore(mark,id,keyArgs)},this)}else{this._extendCore(mark,ids,keyArgs)}},_extendCore:function(mark,id,keyArgs){if(mark){var component=def.getOwn(this._components,id);if(component){if(mark.borderPanel){mark=mark.borderPanel}var logOut=pvc.debug>=3?[]:null;var constOnly=def.get(keyArgs,'constOnly',false);var wrap=mark.wrap;var keyArgs2={tag:pvc.extensionTag};var isRealMark=mark instanceof pv.Mark;component.forEach(function(v,m){if(mark.isLocked&&mark.isLocked(m)){if(logOut){logOut.push(m+": locked extension point!")}}else if(mark.isIntercepted&&mark.isIntercepted(m)){if(logOut){logOut.push(m+":"+pvc.stringify(v)+" (controlled)")}}else{if(logOut){logOut.push(m+": "+pvc.stringify(v))}if(v!=null){var type=typeof v;if(type==='object'){if(m==='svg'||m==='css'){var v2=mark.propertyValue(m);if(v2){v=def.copy(v2,v)}}}else if(isRealMark&&(wrap||constOnly)&&type==='function'){if(constOnly){return}if(m!=='add'){v=wrap.call(mark,v,m)}}}if(typeof mark[m]==="function"){if(m!='add'&&mark.intercept){mark.intercept(m,v,keyArgs2)}else{mark[m](v)}}else{mark[m]=v}}});if(logOut){if(logOut.length){this._log("Applying Extension Points for: '"+id+"'\n\t* "+logOut.join("\n\t* "))}else if(pvc.debug>=5){this._log("No Extension Points for: '"+id+"'")}}}}else if(pvc.debug>=4){this._log("Applying Extension Points for: '"+id+"' (target mark does not exist)")}},_getExtension:function(id,prop){var component;if(!def.array.is(id)){component=def.getOwn(this._components,id);if(component){return component.get(prop)}}else{var i=id.length-1,value;while(i>=0){component=def.getOwn(this._components,id[i--]);if(component&&(value=component.get(prop))!==undefined){return value}}}},_getConstantExtension:function(id,prop){var value=this._getExtension(id,prop);if(!def.fun.is(value)){return value}}}); -def.type('pvc.BasePanel',pvc.Abstract).init(function(chart,parent,options){this.chart=chart;this.base();this.axes={};if(options){if(options.scenes){this._sceneTypeExtensions=options.scenes;delete options.scenes}var axes=options.axes;if(axes){def.copy(this.axes,axes);delete options.axes}}$.extend(this,options);this.chart=chart;if(!this.axes.color){this.axes.color=chart.axes.color}this.position={};var margins=options&&options.margins;if(!parent&&margins===undefined){margins=3}this.margins=new pvc.Sides(margins);this.paddings=new pvc.Sides(options&&options.paddings);this.size=new pvc.Size(options&&options.size);this.sizeMax=new pvc.Size(options&&options.sizeMax);if(!parent){this.parent=null;this.root=this;this.topRoot=this;this.isRoot=true;this.isTopRoot=true;this.data=this.chart.data}else{this.parent=parent;this.isTopRoot=false;this.isRoot=(parent.chart!==chart);this.root=this.isRoot?this:parent.root;this.topRoot=parent.topRoot;this.data=parent.data;if(this.isRoot){this.position.left=chart.left;this.position.top=chart.top}parent._addChild(this)}if(this.isRoot){this.anchor=null;this.align=null;this.alignTo=null;this.offset=null}else{this.align=pvc.parseAlign(this.anchor,this.align);var alignTo=this.alignTo;var side=this.anchor;if(alignTo!=null&&alignTo!==''&&(side==='left'||side==='right')){if(alignTo!=='page-middle'){if(!isNaN(+alignTo.charAt(0))){alignTo=pvc.PercentValue.parse(alignTo)}else{alignTo=pvc.parseAlign(side,alignTo)}}}else{alignTo=this.align}this.alignTo=alignTo;this.offset=new pvc.Offset(this.offset)}if(this.borderWidth==null){var borderWidth;var extensionId=this._getExtensionId();if(extensionId){var strokeStyle=this._getExtension(extensionId,'strokeStyle');if(strokeStyle!=null){borderWidth=+this._getConstantExtension(extensionId,'lineWidth');if(isNaN(borderWidth)||!isFinite(borderWidth)){borderWidth=null}}}this.borderWidth=borderWidth==null?0:1.5}}).add({chart:null,parent:null,_children:null,type:pv.Panel,_extensionPrefix:'',height:null,width:null,borderWidth:null,anchor:"top",pvPanel:null,margins:null,paddings:null,isRoot:false,isTopRoot:false,root:null,topRoot:null,_layoutInfo:null,_signs:null,data:null,dataPartValue:null,_isAnimating:0,_isRubberBandSelecting:false,_ignoreClicks:0,_v1DimRoleName:{'series':'series','category':'category','value':'value'},_sceneTypeExtensions:null,clickAction:null,doubleClickAction:null,compatVersion:function(options){return this.chart.compatVersion(options)},_createLogInstanceId:function(){return""+this.constructor+this.chart._createLogChildSuffix()},defaultVisibleBulletGroupScene:function(){var colorAxis=this.axes.color;if(colorAxis&&colorAxis.option('LegendVisible')){var dataPartValue=this.dataPartValue;return def.query(colorAxis.dataCells).where(function(dataCell){return dataCell.dataPartValue===dataPartValue}).select(function(dataCell){return dataCell.legendBulletGroupScene}).first(def.truthy)}return null},_getLegendBulletRootScene:function(){return this.chart._getLegendBulletRootScene()},_addChild:function(child){child.parent===this||def.assert("Child has a != parent.");(this._children||(this._children=[])).push(child)},_addSign:function(sign){(this._signs||(this._signs=[])).push(sign)},visibleData:function(){return this.chart.visibleData(this.dataPartValue)},layout:function(availableSize,keyArgs){if(!this._layoutInfo||def.get(keyArgs,'force',false)){var referenceSize=def.get(keyArgs,'referenceSize');if(!referenceSize&&availableSize){referenceSize=def.copyOwn(availableSize)}var desiredSize=this.size.resolve(referenceSize);var sizeMax=this.sizeMax.resolve(referenceSize);if(!availableSize){if(desiredSize.width==null||desiredSize.height==null){throw def.error.operationInvalid("Panel layout without width or height set.")}availableSize=def.copyOwn(desiredSize)}if(!referenceSize&&availableSize){referenceSize=def.copyOwn(availableSize)}if(sizeMax.width!=null&&availableSize.width>sizeMax.width){availableSize.width=sizeMax.width}if(sizeMax.height!=null&&availableSize.height>sizeMax.height){availableSize.height=sizeMax.height}var halfBorder=this.borderWidth/2;var realMargins=(def.get(keyArgs,'margins')||this.margins).resolve(referenceSize);var realPaddings=(def.get(keyArgs,'paddings')||this.paddings).resolve(referenceSize);var margins=pvc.Sides.inflate(realMargins,halfBorder);var paddings=pvc.Sides.inflate(realPaddings,halfBorder);var spaceWidth=margins.width+paddings.width;var spaceHeight=margins.height+paddings.height;var availableClientSize=new pvc.Size(Math.max(availableSize.width-spaceWidth,0),Math.max(availableSize.height-spaceHeight,0));var desiredClientSize=def.copyOwn(desiredSize);if(desiredClientSize.width!=null){desiredClientSize.width=Math.max(desiredClientSize.width-spaceWidth,0)}if(desiredClientSize.height!=null){desiredClientSize.height=Math.max(desiredClientSize.height-spaceHeight,0)}var prevLayoutInfo=this._layoutInfo||null;var canChange=def.get(keyArgs,'canChange',true);var layoutInfo=this._layoutInfo={canChange:canChange,referenceSize:referenceSize,realMargins:realMargins,realPaddings:realPaddings,borderWidth:this.borderWidth,margins:margins,paddings:paddings,desiredClientSize:desiredClientSize,clientSize:availableClientSize,pageClientSize:prevLayoutInfo?prevLayoutInfo.pageClientSize:availableClientSize.clone(),previous:prevLayoutInfo};if(prevLayoutInfo){delete prevLayoutInfo.previous;delete prevLayoutInfo.pageClientSize}var clientSize=this._calcLayout(layoutInfo);var size;if(!clientSize){size=availableSize;clientSize=availableClientSize}else{layoutInfo.clientSize=clientSize;size={width:clientSize.width+spaceWidth,height:clientSize.height+spaceHeight}}this.isVisible=(clientSize.width>0&&clientSize.height>0);delete layoutInfo.desiredClientSize;this.width=size.width;this.height=size.height;if(!canChange&&prevLayoutInfo){delete layoutInfo.previous}if(pvc.debug>=5){this._log("Size = "+pvc.stringify(size));this._log("Margins = "+pvc.stringify(layoutInfo.margins));this._log("Paddings = "+pvc.stringify(layoutInfo.paddings));this._log("ClientSize = "+pvc.stringify(layoutInfo.clientSize))}this._onLaidOut()}},_onLaidOut:function(){if(this.isRoot){this.chart._onLaidOut()}},_calcLayout:function(layoutInfo){var clientSize;var me=this;var margins,remSize,useLog;if(me._children){var aolMap=pvc.BasePanel.orthogonalLength;var aoMap=pvc.BasePanel.relativeAnchor;var altMap=pvc.BasePanel.leftTopAnchor;var aofMap=pvc.Offset.namesSidesToOffset;var fillChildren=[];var sideChildren=[];me._children.forEach(function(child){var a=child.anchor;if(a){if(a==='fill'){fillChildren.push(child)}else{def.hasOwn(aoMap,a)||def.fail.operationInvalid("Unknown anchor value '{0}'",[a]);sideChildren.push(child)}}});useLog=pvc.debug>=5;clientSize=def.copyOwn(layoutInfo.clientSize);var childKeyArgs={force:true,referenceSize:clientSize};if(useLog){me._group("CCC DOCK LAYOUT clientSize = "+pvc.stringify(clientSize))}try{doMaxTimes(5,layoutCycle,me)}finally{if(useLog){me._groupEnd()}}}return clientSize;function doMaxTimes(maxTimes,fun,ctx){var index=0;while(maxTimes--){if(fun.call(ctx,maxTimes,index)===false){return true}index++}return false}function layoutCycle(remTimes,iteration){if(useLog){me._group("LayoutCycle #"+(iteration+1)+" (remaining: "+remTimes+")")}try{var canResize=(remTimes>0);margins=new pvc.Sides(0);remSize=def.copyOwn(clientSize);var child;var index=0;var count=sideChildren.length;while(index0;child.layout(new pvc.Size(remSize),childKeyArgs);if(child.isVisible){resized=checkChildResize.call(this,child,canResize);if(resized){return false}var requestPaddings=child._layoutInfo.requestPaddings;if(checkPaddingsChanged(paddings,requestPaddings)){paddings=requestPaddings;if(remTimes>0){paddings=new pvc.Sides(paddings);if(useLog){this._log("Child requested paddings change: "+pvc.stringify(paddings))}return true}if(pvc.debug>=2){this._warn("Child requests paddings change but iterations limit has been reached.")}}positionChild.call(this,child);if(child.anchor!=='fill'){updateSide.call(this,child)}}return false}finally{if(useLog){me._groupEnd()}}},this);return resized}function checkPaddingsChanged(paddings,newPaddings){if(!newPaddings){return false}return def.query(pvc.Sides.names).each(function(side){var curPad=(paddings&&paddings[side])||0;var newPad=(newPaddings&&newPaddings[side])||0;if(Math.abs(newPad-curPad)>=0.1){return false}})}function checkChildResize(child,canResize){var resized=false;var addWidth=child.width-remSize.width;if(addWidth>0){if(pvc.debug>=3){this._log("Child added width = "+addWidth)}if(!canResize){if(pvc.debug>=2){this._warn("Child wanted more width, but layout iterations limit has been reached.")}}else{resized=true;remSize.width+=addWidth;clientSize.width+=addWidth}}var addHeight=child.height-remSize.height;if(addHeight>0){if(pvc.debug>=3){this._log("Child added height ="+addHeight)}if(!canResize){if(pvc.debug>=2){this._warn("Child wanted more height, but layout iterations limit has been reached.")}}else{resized=true;remSize.height+=addHeight;clientSize.height+=addHeight}}return resized}function positionChild(child){var side=child.anchor;var align=child.align;var alignTo=child.alignTo;var sidePos;if(side==='fill'){side='left';sidePos=margins.left+remSize.width/2-(child.width/2);align=alignTo='middle'}else{sidePos=margins[side]}var sideo,sideOPosChildOffset;switch(align){case'top':case'bottom':case'left':case'right':sideo=align;sideOPosChildOffset=0;break;case'center':case'middle':sideo=altMap[aoMap[side]];sideOPosChildOffset=-child[aolMap[sideo]]/2;break}var sideOPosParentOffset;var sideOTo;switch(alignTo){case'top':case'bottom':case'left':case'right':sideOTo=alignTo;sideOPosParentOffset=(sideOTo!==sideo)?remSize[aolMap[sideo]]:0;break;case'center':case'middle':sideOTo=altMap[aoMap[side]];sideOPosParentOffset=remSize[aolMap[sideo]]/2;break;case'page-center':case'page-middle':sideOTo=altMap[aoMap[side]];var lenProp=aolMap[sideo];var pageLen=Math.min(remSize[lenProp],layoutInfo.pageClientSize[lenProp]);sideOPosParentOffset=pageLen/2;break}var sideOPos=margins[sideOTo]+sideOPosParentOffset+sideOPosChildOffset;var resolvedOffset=child.offset.resolve(remSize);if(resolvedOffset){sidePos+=resolvedOffset[aofMap[side]]||0;sideOPos+=resolvedOffset[aofMap[sideo]]||0}if(child.keepInBounds){if(sidePos<0){sidePos=0}if(sideOPos<0){sideOPos=0}}child.setPosition(def.set({},side,sidePos,sideo,sideOPos))}function updateSide(child){var side=child.anchor;var sideol=aolMap[side];var olen=child[sideol];margins[side]+=olen;remSize[sideol]-=olen}},invalidateLayout:function(){this._layoutInfo=null;if(this._children){this._children.forEach(function(child){child.invalidateLayout()})}},_create:function(force){if(!this.pvPanel||force){this.pvPanel=null;delete this._signs;this.layout();if(!this.isVisible){return}if(this.isRoot){this._creating()}var margins=this._layoutInfo.margins;var paddings=this._layoutInfo.paddings;if(this.isTopRoot){this.pvRootPanel=this.pvPanel=new pv.Panel().canvas(this.chart.options.canvas);if(margins.width>0||margins.height>0){this.pvPanel.width(this.width).height(this.height);this.pvPanel=this.pvPanel.add(pv.Panel)}}else{this.pvPanel=this.parent.pvPanel.add(this.type)}var pvBorderPanel=this.pvPanel;var width=this.width-margins.width;var height=this.height-margins.height;pvBorderPanel.width(width).height(height);if(pvc.debug>=15&&(margins.width>0||margins.height>0)){(this.isTopRoot?this.pvRootPanel:this.parent.pvPanel).add(this.type).width(this.width).height(this.height).left(this.position.left!=null?this.position.left:null).right(this.position.right!=null?this.position.right:null).top(this.position.top!=null?this.position.top:null).bottom(this.position.bottom!=null?this.position.bottom:null).strokeStyle('orange').lineWidth(1).strokeDasharray('- .')}var hasPositions={};def.eachOwn(this.position,function(v,side){pvBorderPanel[side](v+margins[side]);hasPositions[this.anchorLength(side)]=true},this);if(!hasPositions.width){if(margins.left>0){pvBorderPanel.left(margins.left)}if(margins.right>0){pvBorderPanel.right(margins.right)}}if(!hasPositions.height){if(margins.top>0){pvBorderPanel.top(margins.top)}if(margins.bottom>0){pvBorderPanel.bottom(margins.bottom)}}if(paddings.width>0||paddings.height>0){this.pvPanel=pvBorderPanel.add(pv.Panel).width(width-paddings.width).height(height-paddings.height).left(paddings.left).top(paddings.top)}pvBorderPanel.borderPanel=pvBorderPanel;pvBorderPanel.paddingPanel=this.pvPanel;this.pvPanel.paddingPanel=this.pvPanel;this.pvPanel.borderPanel=pvBorderPanel;if(pvc.debug>=15){this.pvPanel.strokeStyle('lightgreen').lineWidth(1).strokeDasharray('- ');if(this.pvPanel!==pvBorderPanel){pvBorderPanel.strokeStyle('blue').lineWidth(1).strokeDasharray('. ')}}var extensionId=this._getExtensionId();new pvc.visual.Panel(this,null,{panel:pvBorderPanel,extensionId:extensionId});this._createCore(this._layoutInfo);if(this.isTopRoot&&pv.renderer()!=='batik'&&this.chart._canSelectWithRubberband()){this._initRubberBand()}this.applyExtensions()}},_creating:function(){if(this._children){this._children.forEach(function(child){child._creating()})}},_createCore:function(){if(this._children){this._children.forEach(function(child){child._create()})}},render:function(keyArgs){if(!this.isTopRoot){return this.topRoot.render(keyArgs)}this._create(def.get(keyArgs,'recreate',false));if(!this.isVisible){return}this._onRender();var options=this.chart.options;var pvPanel=this.pvRootPanel;var animate=this.chart._animatable&&options.animate;this._isAnimating=animate&&!def.get(keyArgs,'bypassAnimation',false)?1:0;try{pvPanel.render();if(this._isAnimating){this._isAnimating=2;var me=this;pvPanel.transition().duration(2000).ease("cubic-in-out").start(function(){me._isAnimating=0;me._onRenderEnd(true)})}else{this._onRenderEnd(false)}}finally{this._isAnimating=0}},_onRender:function(){var renderCallback=this.chart.options.renderCallback;if(renderCallback){if(this.compatVersion()<=1){renderCallback.call(this.chart)}else{var context=this._getContext();renderCallback.call(context,context.scene)}}},_onRenderEnd:function(animated){if(this._children){this._children.forEach(function(child){child._onRenderEnd(animated)})}},renderInteractive:function(){if(this.isVisible){var pvMarks=this._getSelectableMarks();if(pvMarks&&pvMarks.length){pvMarks.forEach(function(pvMark){pvMark.render()})}else if(!this._children){this.pvPanel.render();return}if(this._children){this._children.forEach(function(child){child.renderInteractive()})}}},_getSelectableMarks:function(){return null},animate:function(start,end){return(this.topRoot._isAnimating===1)?start:end},isAnimatingStart:function(){return(this.topRoot._isAnimating===1)},isAnimating:function(){return(this.topRoot._isAnimating>0)},setPosition:function(position){for(var side in position){if(def.hasOwn(pvc.Sides.namesSet,side)){var s=position[side];if(s===null){delete this.position[side]}else{s=+s;if(!isNaN(s)&&isFinite(s)){this.position[side]=s}}}}},createAnchoredSize:function(anchorLength,size){if(this.isAnchorTopOrBottom()){return new pvc.Size(size.width,Math.min(size.height,anchorLength))}return new pvc.Size(Math.min(size.width,anchorLength),size.height)},applyExtensions:function(){if(this._signs){this._signs.forEach(function(sign){sign.applyExtensions()})}},extend:function(mark,id,keyArgs){this.chart.extend(mark,this._makeExtensionAbsId(id),keyArgs)},extendAbs:function(mark,absId,keyArgs){this.chart.extend(mark,absId,keyArgs)},_extendSceneType:function(typeKey,type,names){var typeExts=def.get(this._sceneTypeExtensions,typeKey);if(typeExts){pvc.extendType(type,typeExts,names)}},_absBaseExtId:{abs:'base'},_absSmallBaseExtId:{abs:'smallBase'},_getExtensionId:function(){if(this.isRoot){return!this.chart.parent?this._absBaseExtId:this._absSmallBaseExtId}},_getExtensionPrefix:function(){return this._extensionPrefix},_makeExtensionAbsId:function(id){return pvc.makeExtensionAbsId(id,this._getExtensionPrefix())},_getExtension:function(id,prop){return this.chart._getExtension(this._makeExtensionAbsId(id),prop)},_getExtensionAbs:function(absId,prop){return this.chart._getExtension(absId,prop)},_getConstantExtension:function(id,prop){return this.chart._getConstantExtension(this._makeExtensionAbsId(id),prop)},getPvPanel:function(layer){var mainPvPanel=this.pvPanel;if(!layer){return mainPvPanel}if(!this.parent){throw def.error.operationInvalid("Layers are not possible in a root panel.")}if(!mainPvPanel){throw def.error.operationInvalid("Cannot access layer panels without having created the main panel.")}var pvPanel=null;if(!this._layers){this._layers={}}else{pvPanel=this._layers[layer]}if(!pvPanel){var pvParentPanel=this.parent.pvPanel;pvPanel=pvParentPanel.borderPanel.add(this.type).extend(mainPvPanel.borderPanel);var pvBorderPanel=pvPanel;if(mainPvPanel!==mainPvPanel.borderPanel){pvPanel=pvBorderPanel.add(pv.Panel).extend(mainPvPanel)}pvBorderPanel.borderPanel=pvBorderPanel;pvBorderPanel.paddingPanel=pvPanel;pvPanel.paddingPanel=pvPanel;pvPanel.borderPanel=pvBorderPanel;this.initLayerPanel(pvPanel,layer);this._layers[layer]=pvPanel}return pvPanel},initLayerPanel:function(){},_getV1DimName:function(v1Dim){var dimNames=this._v1DimName||(this._v1DimNameCache={});var dimName=dimNames[v1Dim];if(dimName==null){var role=this.chart.visualRoles(this._v1DimRoleName[v1Dim],{assertExists:false});dimName=role?role.firstDimensionName():'';dimNames[v1Dim]=dimName}return dimName},_getV1Datum:function(scene){return scene.datum},_createContext:function(mark,ev){return new pvc.visual.Context(this,mark,ev)},_getContext:function(mark,ev){var context=this._context;if(!context||context.isPinned){this._context=this._createContext(mark,ev)}else{visualContext_update.call(context,mark,ev)}return this._context},_isTooltipEnabled:function(){return!this.isRubberBandSelecting()&&!this.isAnimating()},_ensurePropEvents:function(pvMark){var events=pvMark.propertyValue('events',true);if(!events||events==='none'){pvMark.events('all')}},_addPropHoverable:function(pvMark){var panel=this;var onEvent;var offEvent;onEvent='mouseover';offEvent='mouseout';pvMark.event(onEvent,function(scene){if(!panel.isRubberBandSelecting()&&!panel.isAnimating()){scene.setActive(true);panel.renderInteractive()}}).event(offEvent,function(scene){if(!panel.isRubberBandSelecting()&&!panel.isAnimating()){if(scene.clearActive()){panel.renderInteractive()}}});this._ensurePropEvents(pvMark)},_addPropTooltip:function(pvMark,keyArgs){var chartTipOptions=this.chart._tooltipOptions;var tipOptions;var nowTipOptions=def.get(keyArgs,'options');if(nowTipOptions){tipOptions=def.create(chartTipOptions,nowTipOptions)}else{tipOptions=Object.create(chartTipOptions)}var buildTooltip=def.get(keyArgs,'buildTooltip')||this._getTooltipBuilder(tipOptions);if(!buildTooltip){return}tipOptions.isEnabled=this._isTooltipEnabled.bind(this);var tipsyEvent=def.get(keyArgs,'tipsyEvent');if(!tipsyEvent){tipsyEvent='mouseover'}var isLazy=def.get(keyArgs,'isLazy',true);pvMark.localProperty("tooltip").tooltip(this._createTooltipProp(pvMark,buildTooltip,isLazy)).title(function(){return''}).event(tipsyEvent,pv.Behavior.tipsy(tipOptions));this._ensurePropEvents(pvMark)},_getTooltipBuilder:function(tipOptions){var options=this.chart.options;var isV1Compat=this.compatVersion()<=1;var tooltipFormat=tipOptions.format;if(!tooltipFormat){if(!isV1Compat){return this._buildDataTooltip}tooltipFormat=options.v1StyleTooltipFormat;if(!tooltipFormat){return}}if(isV1Compat){return function(context){return tooltipFormat.call(context.panel,context.getV1Series(),context.getV1Category(),context.getV1Value()||'',context.getV1Datum())}}return function(context){return tooltipFormat.call(context,context.scene)}},_createTooltipProp:function(pvMark,buildTooltip,isLazy){var myself=this;if(!isLazy){return function(){var context=myself._getContext(pvMark,null);if(context.scene.isIntermediate){return null}return buildTooltip.call(myself,context)}}return function(){var context=myself._getContext(pvMark,null);if(context.scene.isIntermediate){return null}context.pin();var tooltip;return function(){if(tooltip==null){tooltip=buildTooltip.call(myself,context);context=null}return tooltip}}},_requirePointEvent:function(radius){if(!this.isTopRoot){return this.topRoot._requirePointEvent(radius)}if(!this._attachedPointEvent){this.pvPanel.events('all').event("mousemove",pv.Behavior.point(radius||20));this._attachedPointEvent=true}},_buildDataTooltip:function(context){var scene=context.scene;if(!scene.datum){return""}var group=scene.group;var isMultiDatumGroup=group&&group.count()>1;var firstDatum=scene.datum;if(!isMultiDatumGroup&&(!firstDatum||firstDatum.isNull)){return""}var data=this.data;var visibleKeyArgs={visible:true};var tooltip=[];if(firstDatum.isInterpolated){tooltip.push('Interpolation: '+def.html.escape(firstDatum.interpolation)+'
')}else if(firstDatum.isTrend){tooltip.push('Trend: '+def.html.escape(firstDatum.trendType)+'
')}var complexType=data.type;var playingPercentMap=context.panel.stacked===false?null:complexType.getPlayingPercentVisualRoleDimensionMap();var percentValueFormat=playingPercentMap?this.chart.options.percentValueFormat:null;var commonAtoms=isMultiDatumGroup?group.atoms:scene.datum.atoms;var commonAtomsKeys=complexType.sortDimensionNames(def.keys(commonAtoms));function addDim(escapedDimLabel,label){tooltip.push(''+escapedDimLabel+": "+(def.html.escape(label)||" - ")+'
')}function calcPercent(atom,dimName){var pct;if(group){pct=group.dimensions(dimName).percentOverParent(visibleKeyArgs)}else{pct=data.dimensions(dimName).percent(atom.value)}return percentValueFormat(pct)}var anyCommonAtom=false;commonAtomsKeys.forEach(function(dimName){var atom=commonAtoms[dimName];var dimType=atom.dimension.type;if(!dimType.isHidden){if(!isMultiDatumGroup||atom.value!=null){anyCommonAtom=true;var valueLabel=atom.label;if(playingPercentMap&&playingPercentMap.has(dimName)){valueLabel+=" ("+calcPercent(atom,dimName)+")"}addDim(def.html.escape(atom.dimension.type.label),valueLabel)}}},this);if(isMultiDatumGroup){if(anyCommonAtom){tooltip.push('
')}tooltip.push("#: "+group._datums.length+'
');complexType.sortDimensionNames(group.freeDimensionNames()).forEach(function(dimName){var dim=group.dimensions(dimName);if(!dim.type.isHidden){var dimLabel=def.html.escape(dim.type.label),valueLabel;if(dim.type.valueType===Number){valueLabel=dim.format(dim.sum(visibleKeyArgs));if(playingPercentMap&&playingPercentMap.has(dimName)){valueLabel+=" ("+calcPercent(null,dimName)+")"}dimLabel="∑ "+dimLabel}else{valueLabel=dim.atoms(visibleKeyArgs).map(function(atom){return atom.label||"- "}).join(", ")}addDim(dimLabel,valueLabel)}})}return'
'+tooltip.join('\n')+'
'},_addPropClick:function(pvMark){var myself=this;function onClick(){var ev=arguments[arguments.length-1];return myself._handleClick(this,ev)}pvMark.cursor("pointer").event("click",onClick);this._ensurePropEvents(pvMark)},_addPropDoubleClick:function(pvMark){var myself=this;function onDoubleClick(){var ev=arguments[arguments.length-1];return myself._handleDoubleClick(this,ev)}pvMark.cursor("pointer").event("dblclick",onDoubleClick);this._ensurePropEvents(pvMark)},_isDoubleClickable:function(keyArgs){var options=keyArgs||this.chart.options;return options.clickable&&!!this.doubleClickAction},_handleDoubleClick:function(pvMark,ev){if(!this._isDoubleClickable()){return}this._ignoreClicks=2;var sign=pvMark.sign;if(!sign||sign.isDoubleClickable()){var context=this._getContext(pvMark,ev);this._onDoubleClick(context)}},_onDoubleClick:function(context){var handler=this.doubleClickAction;if(handler){if(this.compatVersion()<=1){this._onV1DoubleClick(context,handler)}else{handler.call(context,context.scene)}}},_onV1DoubleClick:function(context,handler){handler.call(context.pvMark,context.getV1Series(),context.getV1Category(),context.getV1Value(),context.event,context.getV1Datum())},_isClickable:function(){return this.chart.options.clickable&&!!this.clickAction},_shouldHandleClick:function(){return this.chart._canSelectWithClick()||this._isClickable()},_handleClick:function(pvMark,ev){if(!this._shouldHandleClick()){return}var options=this.chart.options,context;if(!this.doubleClickAction){context=this._getContext(pvMark,ev);this._handleClickCore(context)}else{var myself=this;context=this._createContext(pvMark,ev);window.setTimeout(function(){myself._handleClickCore.call(myself,context)},options.doubleClickMaxDelay||300)}},_handleClickCore:function(context){if(this._ignoreClicks){this._ignoreClicks--}else{var sign=context.sign;if(!sign||sign.isClickable()){this._onClick(context)}if((sign&&sign.isSelectable())||(!sign&&this.chart.options.selectable&&context.scene.datum)){this._onSelect(context)}}},_onClick:function(context){var handler=this.clickAction;if(handler){if(this.compatVersion()<=1){this._onV1Click(context,handler)}else{handler.call(context,context.scene)}}},_onV1Click:function(context,handler){handler.call(context.pvMark,context.getV1Series(),context.getV1Category(),context.getV1Value(),context.event,context.getV1Datum())},_onSelect:function(context){var datums=context.scene.datums().array();if(datums.length){var chart=this.chart;chart._updatingSelections(function(){datums=chart._onUserSelection(datums);if(datums&&datums.length){if(chart.options.ctrlSelectMode&&!context.event.ctrlKey){chart.data.replaceSelected(datums)}else{pvc.data.Data.toggleSelected(datums)}}},this)}},isRubberBandSelecting:function(){return this.topRoot._isRubberBandSelecting},_initRubberBand:function(){var myself=this,chart=this.chart,options=chart.options,data=chart.data;var dMin2=4;this._isRubberBandSelecting=false;var rubberPvParentPanel=this.pvRootPanel||this.pvPanel.paddingPanel,toScreen,rb;var selectBar=this.selectBar=new pvc.visual.Bar(this,rubberPvParentPanel,{extensionId:'rubberBand',normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true}).override('defaultStrokeWidth',function(){return 1.5}).override('defaultColor',function(type){return type==='stroke'?'#86fe00':'rgba(203, 239, 163, 0.6)'}).override('interactiveColor',function(color){return color}).pvMark.lock('visible',function(){return!!rb}).lock('left',function(){return rb.x}).lock('right').lock('top',function(){return rb.y}).lock('bottom').lock('width',function(){return rb.dx}).lock('height',function(){return rb.dy}).lock('cursor').lock('events','none');if(!this._getExtensionAbs('base','fillStyle')){rubberPvParentPanel.fillStyle(pvc.invisibleFill)}rubberPvParentPanel.lock('events','all');var scene=new pvc.visual.Scene(null,{panel:this});scene.x=scene.y=scene.dx=scene.dy=0;var selectionEndedDate;rubberPvParentPanel.lock('data',[scene]).event('mousedown',pv.Behavior.select().autoRender(false)).event('select',function(){if(!rb){if(myself.isAnimating()){return}if(scene.dx*scene.dx+scene.dy*scene.dy<=dMin2){return}rb=new pv.Shape.Rect(scene.x,scene.y,scene.dx,scene.dy);myself._isRubberBandSelecting=true;if(!toScreen){toScreen=rubberPvParentPanel.toScreenTransform()}myself.rubberBand=rb.apply(toScreen)}else{rb=new pv.Shape.Rect(scene.x,scene.y,scene.dx,scene.dy)}selectBar.render()}).event('selectend',function(){if(rb){var ev=arguments[arguments.length-1];if(!toScreen){toScreen=rubberPvParentPanel.toScreenTransform()}var rbs=rb.apply(toScreen);rb=null;myself._isRubberBandSelecting=false;selectBar.render();try{myself._processRubberBand(rbs,ev,{allowAdditive:true})}finally{selectionEndedDate=new Date()}}});if(options.clearSelectionMode==='emptySpaceClick'){rubberPvParentPanel.event("click",function(){if(selectionEndedDate){var timeSpan=new Date()-selectionEndedDate;if(timeSpan<300){selectionEndedDate=null;return}}if(data.owner.clearSelected()){myself.chart.updateSelections()}})}},_processRubberBand:function(rb,ev,keyArgs){this.rubberBand=rb;try{this._onRubberBandSelectionEnd(ev,keyArgs)}finally{this.rubberBand=null}},_onRubberBandSelectionEnd:function(ev,keyArgs){if(pvc.debug>=10){this._log("rubberBand "+pvc.stringify(this.rubberBand))}keyArgs=Object.create(keyArgs||{});keyArgs.toggle=false;var datums=this._getDatumsOnRubberBand(ev,keyArgs);if(datums){var allowAdditive=def.get(keyArgs,'allowAdditive',true);var chart=this.chart;chart._updatingSelections(function(){var clearBefore=!allowAdditive||(!ev.ctrlKey&&chart.options.ctrlSelectMode);if(clearBefore){chart.data.owner.clearSelected();pvc.data.Data.setSelected(datums,true)}else if(keyArgs.toggle){pvc.data.Data.toggleSelected(datums)}else{pvc.data.Data.setSelected(datums,true)}})}},_getDatumsOnRubberBand:function(ev,keyArgs){var datumMap=new def.Map();this._getDatumsOnRect(datumMap,this.rubberBand,keyArgs);var datums=datumMap.values();if(datums.length){datums=this.chart._onUserSelection(datums);if(datums&&!datums.length){datums=null}}return datums},_getDatumsOnRect:function(datumMap,rect,keyArgs){this._getOwnDatumsOnRect(datumMap,rect,keyArgs);if(this._children){this._children.forEach(function(child){child._getDatumsOnRect(datumMap,rect,keyArgs)},this)}},_getOwnDatumsOnRect:function(datumMap,rect,keyArgs){var any=false;if(this.isVisible){var pvMarks=this._getSelectableMarks();if(pvMarks&&pvMarks.length){pvMarks.forEach(function(pvMark){this._eachMarkDatumOnRect(pvMark,rect,function(datum){datumMap.set(datum.id,datum);any=true},this,def.get(keyArgs,'markSelectionMode'))},this)}}return any},_eachMarkDatumOnRect:function(pvMark,rect,fun,ctx,selectionMode){var sign=pvMark.sign;if(sign&&!sign.isSelectable()){return}if(selectionMode==null){selectionMode=def.get(pvMark,'rubberBandSelectionMode','partial')}var useCenter=(selectionMode==='center');pvMark.eachInstanceWithData(function(scenes,index,toScreen){var shape=pvMark.getShape(scenes,index);shape=(useCenter?shape.center():shape).apply(toScreen);processShape.call(this,shape,scenes[index],index)},this);function processShape(shape,instance,index){if(shape.intersectsRect(rect)){var cccScene=instance.data;if(cccScene&&cccScene.datum){var group=cccScene.group;var datums=group?group._datums:def.array.as(cccScene.datum);if(datums){datums.forEach(function(datum){if(!datum.isNull){if(pvc.debug>=20){this._log("Rubbered Datum.key="+datum.key+": "+pvc.stringify(shape)+" mark type: "+pvMark.type+" index="+index)}fun.call(ctx,datum)}},this)}}}}},isAnchorTopOrBottom:function(anchor){if(!anchor){anchor=this.anchor}return anchor==="top"||anchor==="bottom"},anchorOrtho:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.relativeAnchor[anchor]},anchorOrthoMirror:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.relativeAnchorMirror[anchor]},anchorOpposite:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.oppositeAnchor[anchor]},anchorLength:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.parallelLength[anchor]},anchorOrthoLength:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.orthogonalLength[anchor]},isOrientationVertical:function(orientation){return this.chart.isOrientationVertical(orientation)},isOrientationHorizontal:function(orientation){return this.chart.isOrientationHorizontal(orientation)}}).addStatic({relativeAnchor:{top:"left",bottom:"left",left:"bottom",right:"bottom"},leftBottomAnchor:{top:"bottom",bottom:"bottom",left:"left",right:"left"},leftTopAnchor:{top:"top",bottom:"top",left:"left",right:"left"},horizontalAlign:{top:"right",bottom:"left",middle:"center",right:"right",left:"left",center:"center"},verticalAlign:{top:"top",bottom:"bottom",middle:"middle",right:"bottom",left:"top",center:"middle"},verticalAlign2:{top:"top",bottom:"bottom",middle:"middle",right:"top",left:"bottom",center:"middle"},relativeAnchorMirror:{top:"right",bottom:"right",left:"top",right:"top"},oppositeAnchor:{top:"bottom",bottom:"top",left:"right",right:"left"},parallelLength:{top:"width",bottom:"width",right:"height",left:"height"},orthogonalLength:{top:"height",bottom:"height",right:"width",left:"width"},oppositeLength:{width:"height",height:"width"}}); -def.type('pvc.PlotPanel',pvc.BasePanel).init(function(chart,parent,plot,options){this.base(chart,parent,options);this.plot=plot;this._extensionPrefix=plot.extensionPrefixes;this.dataPartValue=plot.option('DataPart');this.axes.color=chart._getAxis('color',(plot.option('ColorAxis')||0)-1);this.orientation=plot.option('Orientation');this.valuesVisible=plot.option('ValuesVisible');this.valuesAnchor=plot.option('ValuesAnchor');this.valuesMask=plot.option('ValuesMask');this.valuesFont=plot.option('ValuesFont');var roles=this.visualRoles=Object.create(chart._visualRoles);var colorRoleName=plot.option('ColorRole');roles.color=colorRoleName?chart.visualRoles(colorRoleName):null;this.chart._addPlotPanel(this)}).add({anchor:'fill',visualRoles:null,_getExtensionId:function(){var extensionIds=['chart','plot'];if(this.plotName){extensionIds.push(this.plotName)}return extensionIds},isOrientationVertical:function(){return this.orientation===pvc.orientation.vertical},isOrientationHorizontal:function(){return this.orientation===pvc.orientation.horizontal}}); -def.type('pvc.MultiChartPanel',pvc.BasePanel).add({anchor:'fill',_multiInfo:null,createSmallCharts:function(){var chart=this.chart;var options=chart.options;var multiChartMax=Number(options.multiChartMax);if(isNaN(multiChartMax)||multiChartMax<1){multiChartMax=Infinity}var multiChartRole=chart.visualRoles('multiChart');var data=chart.data.flattenBy(multiChartRole,{visible:true});var leafCount=data._children.length;var count=Math.min(leafCount,multiChartMax);if(count===0){return}var multiChartColumnsMax=+options.multiChartColumnsMax;if(isNaN(multiChartColumnsMax)||multiChartMax<1){multiChartColumnsMax=3}var colCount=Math.min(count,multiChartColumnsMax);colCount>=1&&isFinite(colCount)||def.assert("Must be at least 1 and finite");var rowCount=Math.ceil(count/colCount);rowCount>=1||def.assert("Must be at least 1");var coordRootAxesByScopeType=this._getCoordinatedRootAxesByScopeType();var coordScopesByType,addChartToScope,indexChartByScope;if(coordRootAxesByScopeType){coordScopesByType={};addChartToScope=function(childChart,scopeType,scopeIndex){var scopes=def.array.lazy(coordScopesByType,scopeType);def.array.lazy(scopes,scopeIndex).push(childChart)};indexChartByScope=function(childChart){if(coordRootAxesByScopeType.row){addChartToScope(childChart,'row',childChart.smallRowIndex)}if(coordRootAxesByScopeType.column){addChartToScope(childChart,'column',childChart.smallColIndex)}if(coordRootAxesByScopeType.global){addChartToScope(childChart,'global',0)}}}var childOptionsBase=this._buildSmallChartsBaseOptions();var ChildClass=chart.constructor;for(var index=0;index0){margins.left=smallMargins.left}if(colIndex0){margins.top=smallMargins.top}if(rowIndexclientWidth?clientWidth:textWidth}else if(desiredWidth>clientWidth){desiredWidth=clientWidth}var lines;if(textWidth>desiredWidth){lines=pvc.text.justify(this.title,desiredWidth,this.font)}else{lines=this.title?[this.title]:[]}var lineHeight=pv.Text.fontHeight(this.font);var realHeight=lines.length*lineHeight;var availableHeight=layoutInfo.clientSize[a_height];var desiredHeight=layoutInfo.desiredClientSize[a_height];if(desiredHeight==null){desiredHeight=realHeight}else if(desiredHeight>availableHeight){desiredHeight=availableHeight}if(realHeight>desiredHeight){var maxLineCount=Math.max(1,Math.floor(desiredHeight/lineHeight));if(lines.length>maxLineCount){var firstCroppedLine=lines[maxLineCount];lines.length=maxLineCount;realHeight=desiredHeight=maxLineCount*lineHeight;var lastLine=lines[maxLineCount-1]+" "+firstCroppedLine;lines[maxLineCount-1]=pvc.text.trimToWidthB(desiredWidth,lastLine,this.font,"..")}}layoutInfo.lines=lines;layoutInfo.topOffset=(desiredHeight-realHeight)/2;layoutInfo.lineSize={width:desiredWidth,height:lineHeight};layoutInfo.a_width=a_width;layoutInfo.a_height=a_height;requestSize[a_width]=desiredWidth;requestSize[a_height]=desiredHeight;return requestSize},_createCore:function(layoutInfo){var rootScene=this._buildScene(layoutInfo);var rotationByAnchor={top:0,right:Math.PI/2,bottom:0,left:-Math.PI/2};var textAlign=pvc.BasePanel.horizontalAlign[this.align];var textAnchor=pvc.BasePanel.leftTopAnchor[this.anchor];var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(itemScene){return v1f.call(this)}}}this.pvLabel=new pvc.visual.Label(this,this.pvPanel,{extensionId:'label',wrapper:wrapper}).lock('data',rootScene.lineScenes).pvMark[textAnchor](function(lineScene){return layoutInfo.topOffset+lineScene.vars.size.height/2+this.index*lineScene.vars.size.height}).textAlign(textAlign)[this.anchorOrtho(textAnchor)](function(lineScene){switch(this.textAlign()){case'center':return lineScene.vars.size.width/2;case'left':return 0;case'right':return lineScene.vars.size.width}}).text(function(lineScene){return lineScene.vars.textLines[this.index]}).font(this.font).textBaseline('middle').textAngle(rotationByAnchor[this.anchor])},_buildScene:function(layoutInfo){var rootScene=new pvc.visual.Scene(null,{panel:this,group:this.chart.data});var textLines=layoutInfo.lines;rootScene.vars.size=layoutInfo.lineSize;rootScene.vars.textLines=textLines;rootScene.lineScenes=def.array.create(textLines.length,rootScene);return rootScene},_getExtensionId:function(){return''}}); -def.type('pvc.TitlePanel',pvc.TitlePanelAbstract).init(function(chart,parent,options){if(!options){options={}}var isV1Compat=chart.compatVersion()<=1;if(isV1Compat){var size=options.titleSize;if(size==null){options.titleSize=25}}this._extensionPrefix=!chart.parent?"title":"smallTitle";this.base(chart,parent,options)}).add({font:"14px sans-serif",defaultPaddings:4}); -def.type('pvc.LegendPanel',pvc.BasePanel).add({pvRule:null,pvDot:null,pvLabel:null,anchor:'bottom',pvLegendPanel:null,textMargin:6,itemPadding:2.5,markerSize:15,font:'10px sans-serif',_calcLayout:function(layoutInfo){return this._getBulletRootScene().layout(layoutInfo)},_createCore:function(layoutInfo){var clientSize=layoutInfo.clientSize,rootScene=this._getBulletRootScene(),itemPadding=rootScene.vars.itemPadding,contentSize=rootScene.vars.size;var isHorizontal=this.isAnchorTopOrBottom();var a_top=isHorizontal?'top':'left';var a_bottom=this.anchorOpposite(a_top);var a_width=this.anchorLength(a_top);var a_height=this.anchorOrthoLength(a_top);var a_center=isHorizontal?'center':'middle';var a_left=isHorizontal?'left':'top';var a_right=this.anchorOpposite(a_left);var leftOffset=0;switch(this.align){case a_right:leftOffset=clientSize[a_width]-contentSize.width;break;case a_center:leftOffset=(clientSize[a_width]-contentSize.width)/2;break}this.pvPanel.overflow("hidden");var pvLegendRowPanel=this.pvPanel.add(pv.Panel).data(rootScene.vars.rows)[a_left](leftOffset)[a_top](function(){var prevRow=this.sibling();return prevRow?(prevRow[a_top]+prevRow[a_height]+itemPadding[a_height]):0})[a_width](function(row){return row.size.width})[a_height](function(row){return row.size.height});var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(itemScene){return v1f.call(this,itemScene.vars.value.rawValue)}}}this.pvLegendPanel=new pvc.visual.Panel(this,pvLegendRowPanel,{extensionId:'panel',wrapper:wrapper,noSelect:false,noClickSelect:true}).lockMark('data',function(row){return row.items}).lock(a_right,null).lock(a_bottom,null).lockMark(a_left,function(clientScene){var itemPadding=clientScene.vars.itemPadding;var prevItem=this.sibling();return prevItem?(prevItem[a_left]+prevItem[a_width]+itemPadding[a_width]):0}).lockMark('height',function(itemScene){return itemScene.vars.clientSize.height}).lockMark(a_top,isHorizontal?function(itemScene){var vars=itemScene.vars;return vars.row.size.height/2-vars.clientSize.height/2}:0).lockMark('width',isHorizontal?function(itemScene){return itemScene.vars.clientSize.width}:function(){return this.parent.width()}).pvMark.def("hidden","false").fillStyle(function(){return this.hidden()=="true"?"rgba(200,200,200,1)":"rgba(200,200,200,0.0001)"}).cursor(function(itemScene){return itemScene.isClickable()?"pointer":null}).event("click",function(itemScene){if(itemScene.isClickable()){return itemScene.click()}});var pvLegendMarkerPanel=new pvc.visual.Panel(this,this.pvLegendPanel).pvMark.left(0).top(0).right(null).bottom(null).width(function(itemScene){return itemScene.vars.markerSize}).height(function(itemScene){return itemScene.vars.clientSize.height});if(pvc.debug>=20){pvLegendRowPanel.strokeStyle('red');this.pvLegendPanel.strokeStyle('green');pvLegendMarkerPanel.strokeStyle('blue')}rootScene.childNodes.forEach(function(groupScene){var pvGroupPanel=new pvc.visual.Panel(this,pvLegendMarkerPanel).pvMark.visible(function(itemScene){return itemScene.parent===groupScene});groupScene.renderer().create(this,pvGroupPanel,groupScene.extensionPrefix,wrapper)},this);this.pvLabel=new pvc.visual.Label(this,pvLegendMarkerPanel.anchor("right"),{extensionId:'label',wrapper:wrapper}).intercept('textStyle',function(itemScene){var baseTextStyle=this.delegateExtension()||"black";return itemScene.isOn()?baseTextStyle:pvc.toGrayScale(baseTextStyle,null,undefined,150)}).pvMark.textAlign('left').text(function(itemScene){return itemScene.vars.value.label}).lock('textMargin',function(itemScene){return itemScene.vars.textMargin-4}).font(function(itemScene){return itemScene.vars.font}).textDecoration(function(itemScene){return itemScene.isOn()?"":"line-through"})},_getExtensionId:function(){return'area'},_getExtensionPrefix:function(){return'legend'},_getSelectableMarks:function(){return[this.pvLegendPanel]},_getBulletRootScene:function(){var rootScene=this._rootScene;if(!rootScene){rootScene=new pvc.visual.legend.BulletRootScene(null,{panel:this,group:this.chart.data,horizontal:this.isAnchorTopOrBottom(),font:this.font,markerSize:this.markerSize,textMargin:this.textMargin,itemPadding:this.itemPadding});this._rootScene=rootScene}return rootScene}}); -def.type('pvc.CartesianAbstract',pvc.BaseChart).init(function(options){this.axesPanels={};this.base(options)}).add({_gridDockPanel:null,axesPanels:null,yAxisPanel:null,xAxisPanel:null,secondXAxisPanel:null,secondYAxisPanel:null,yScale:null,xScale:null,_getSeriesRoleSpec:function(){return{isRequired:true,defaultDimension:'series*',autoCreateDimension:true,requireIsDiscrete:true}},_getColorRoleSpec:function(){return{isRequired:true,defaultDimension:'color*',defaultSourceRole:'series',requireIsDiscrete:true}},_collectPlotAxesDataCells:function(plot,dataCellsByAxisTypeThenIndex){this.base(plot,dataCellsByAxisTypeThenIndex);if(plot.option.isDefined('BaseAxis')){var baseDataCellsByAxisIndex=def.array.lazy(dataCellsByAxisTypeThenIndex,'base');def.array.lazy(baseDataCellsByAxisIndex,plot.option('BaseAxis')-1).push({plot:plot,role:this.visualRoles(plot.option('BaseRole')),dataPartValue:plot.option('DataPart')})}if(plot.option.isDefined('OrthoAxis')){var trend=plot.option('Trend');var isStacked=plot.option.isDefined('Stacked')?plot.option('Stacked'):undefined;var orthoDataCellsByAxisIndex=def.array.lazy(dataCellsByAxisTypeThenIndex,'ortho');var orthoRoleNames=def.array.to(plot.option('OrthoRole'));var dataCellBase={dataPartValue:plot.option('DataPart'),isStacked:isStacked,trend:trend,nullInterpolationMode:plot.option('NullInterpolationMode')};var orthoDataCells=def.array.lazy(orthoDataCellsByAxisIndex,plot.option('OrthoAxis')-1);orthoRoleNames.forEach(function(orthoRoleName){var dataCell=Object.create(dataCellBase);dataCell.role=this.visualRoles(orthoRoleName);orthoDataCells.push(dataCell)},this)}},_addAxis:function(axis){this.base(axis);switch(axis.type){case'base':case'ortho':this.axes[axis.orientedId]=axis;if(axis.v1SecondOrientedId){this.axes[axis.v1SecondOrientedId]=axis}break}return this},_generateTrendsDataCell:function(dataCell){var trend=dataCell.trend;if(trend){var trendInfo=pvc.trends.get(trend.type);var newDatums=[];this._generateTrendsDataCellCore(newDatums,dataCell,trendInfo);if(newDatums.length){this.data.owner.add(newDatums)}}},_generateTrendsDataCellCore:function(dataCell,trendInfo){},_setAxesScales:function(hasMultiRole){this.base(hasMultiRole);if(!hasMultiRole||this.parent){['base','ortho'].forEach(function(type){var axisOfType=this.axesByType[type];if(axisOfType){axisOfType.forEach(this._createAxisScale,this)}},this)}},_createAxisScale:function(axis){var isOrtho=axis.type==='ortho';var isCart=isOrtho||axis.type==='base';var scale=this._createScaleByAxis(axis);if(scale.isNull&&pvc.debug>=3){this._log(def.format("{0} scale for axis '{1}'- no data",[axis.scaleType,axis.id]))}scale=axis.setScale(scale).scale;if(isCart){if(isOrtho&&axis.index===1){this.secondScale=scale}else if(!axis.index){this[axis.orientation+'Scale']=scale}}return scale},_createScaleByAxis:function(axis){var createScale=this['_create'+def.firstUpperCase(axis.scaleType)+'ScaleByAxis'];return createScale.call(this,axis)},_preRenderContent:function(contentOptions){this._createFocusWindow();this._gridDockPanel=new pvc.CartesianGridDockingPanel(this,this.basePanel,{margins:contentOptions.margins,paddings:contentOptions.paddings});['base','ortho'].forEach(function(type){var typeAxes=this.axesByType[type];if(typeAxes){def.query(typeAxes).reverse().each(function(axis){this._createAxisPanel(axis)},this)}},this);this._createPlotPanels(this._gridDockPanel,{clickAction:contentOptions.clickAction,doubleClickAction:contentOptions.doubleClickAction})},_createFocusWindow:function(){if(this._canSelectWithFocusWindow()){var fwData;var fw=this.focusWindow;if(fw){fwData=fw._exportData()}fw=this.focusWindow=new pvc.visual.CartesianFocusWindow(this);if(fwData){fw._importData(fwData)}fw._initFromOptions()}else if(this.focusWindow){delete this.focusWindow}},_createAxisPanel:function(axis){if(axis.option('Visible')){var titlePanel;var title=axis.option('Title');if(!def.empty(title)){titlePanel=new pvc.AxisTitlePanel(this,this._gridDockPanel,axis,{title:title,font:axis.option('TitleFont')||axis.option('Font'),anchor:axis.option('Position'),align:axis.option('TitleAlign'),margins:axis.option('TitleMargins'),paddings:axis.option('TitlePaddings'),titleSize:axis.option('TitleSize'),titleSizeMax:axis.option('TitleSizeMax')})}var panel=new pvc.AxisPanel(this,this._gridDockPanel,axis,{anchor:axis.option('Position'),size:axis.option('Size'),sizeMax:axis.option('SizeMax'),clickAction:axis.option('ClickAction'),doubleClickAction:axis.option('DoubleClickAction'),useCompositeAxis:axis.option('Composite'),font:axis.option('Font'),labelSpacingMin:axis.option('LabelSpacingMin'),tickExponentMin:axis.option('TickExponentMin'),tickExponentMax:axis.option('TickExponentMax'),grid:axis.option('Grid'),gridCrossesMargin:axis.option('GridCrossesMargin'),ruleCrossesMargin:axis.option('RuleCrossesMargin'),zeroLine:axis.option('ZeroLine'),domainRoundMode:axis.option('DomainRoundMode'),desiredTickCount:axis.option('DesiredTickCount'),showTicks:axis.option('Ticks'),showMinorTicks:axis.option('MinorTicks')});if(titlePanel){panel.titlePanel=titlePanel}this.axesPanels[axis.id]=panel;this.axesPanels[axis.orientedId]=panel;if(axis.index<=1&&axis.v1SecondOrientedId){this[axis.v1SecondOrientedId+'AxisPanel']=panel}return panel}},_createDiscreteScaleByAxis:function(axis){var dataPartValues=axis.dataCells.map(function(dataCell){return dataCell.dataPartValue});var baseData=this.visibleData(dataPartValues,{ignoreNulls:false});var data=baseData&&baseData.flattenBy(axis.role);var scale=new pv.Scale.ordinal();if(!data||!data.count()){scale.isNull=true}else{var values=data.children().select(function(child){return def.nullyTo(child.value,"")}).array();scale.domain(values)}return scale},_createTimeSeriesScaleByAxis:function(axis){var extent=this._getContinuousVisibleExtent(axis);var scale=new pv.Scale.linear();if(!extent){scale.isNull=true}else{var dMin=extent.min;var dMax=extent.max;if((dMax-dMin)===0){dMax=new Date(dMax.getTime()+3600000)}scale.domain(dMin,dMax);scale.minLocked=extent.minLocked;scale.maxLocked=extent.maxLocked}return scale},_createNumericScaleByAxis:function(axis){var extent=this._getContinuousVisibleExtentConstrained(axis);var scale=new pv.Scale.linear();if(!extent){scale.isNull=true}else{var tmp;var dMin=extent.min;var dMax=extent.max;if(dMin>dMax){tmp=dMin;dMin=dMax;dMax=tmp}var originIsZero=axis.option('OriginIsZero');if(originIsZero){if(dMin===0){extent.minLocked=true}else if(dMax===0){extent.maxLocked=true}else if((dMin*dMax)>0){if(dMin>0){if(!extent.minLocked){extent.minLocked=true;dMin=0}}else{if(!extent.maxLocked){extent.maxLocked=true;dMax=0}}}}if(dMin>dMax){tmp=dMin;dMin=dMax;dMax=tmp}if(dMax-dMin<=1e-12){if(!extent.minLocked){dMin=dMin!==0?(dMin*0.99):-0.1}if(!extent.maxLocked||extent.minLocked){dMax=dMax!==0?dMax*1.01:0.1}}scale.domain(dMin,dMax);scale.minLocked=extent.minLocked;scale.maxLocked=extent.maxLocked}return scale},_onLaidOut:function(){if(this.plotPanelList&&this.plotPanelList[0]){['base','ortho'].forEach(function(type){var axes=this.axesByType[type];if(axes){axes.forEach(this._setCartAxisScaleRange,this)}},this)}},_setCartAxisScaleRange:function(axis){var info=this.plotPanelList[0]._layoutInfo;var size=info.clientSize;var length=(axis.orientation==='x')?size.width:size.height;axis.setScaleRange(length);return axis.scale},_getAxesRoundingPaddings:function(){var axesPaddings={};var axesByType=this.axesByType;['base','ortho'].forEach(function(type){var typeAxes=axesByType[type];if(typeAxes){typeAxes.forEach(processAxis)}});return axesPaddings;function setSide(side,pct,locked){var value=axesPaddings[side];if(value==null||pct>value){axesPaddings[side]=pct;axesPaddings[side+'Locked']=locked}else if(locked){axesPaddings[side+'Locked']=locked}}function processAxis(axis){if(axis){var tickRoundPads=axis.getScaleRoundingPaddings();if(tickRoundPads){var isX=axis.orientation==='x';setSide(isX?'left':'bottom',tickRoundPads.begin,tickRoundPads.beginLocked);setSide(isX?'right':'top',tickRoundPads.end,tickRoundPads.endLocked)}}}},_warnSingleContinuousValueRole:function(valueRole){if(!valueRole.grouping.isSingleDimension){this._log("[WARNING] A linear scale can only be obtained for a single dimension role.")}if(valueRole.grouping.isDiscrete()){this._log("[WARNING] The single dimension of role '{0}' should be continuous.",[valueRole.name])}},_getContinuousVisibleExtentConstrained:function(axis,min,max){var minLocked=false;var maxLocked=false;if(min==null){min=axis.option('FixedMin');minLocked=(min!=null)}if(max==null){max=axis.option('FixedMax');maxLocked=(max!=null)}if(min==null||max==null){var baseExtent=this._getContinuousVisibleExtent(axis);if(!baseExtent){return null}if(min==null){min=baseExtent.min}if(max==null){max=baseExtent.max}}return{min:min,max:max,minLocked:minLocked,maxLocked:maxLocked}},_getContinuousVisibleExtent:function(valueAxis){var dataCells=valueAxis.dataCells;if(dataCells.length===1){return this._getContinuousVisibleCellExtent(valueAxis,dataCells[0])}return def.query(dataCells).select(function(dataCell){return this._getContinuousVisibleCellExtent(valueAxis,dataCell)},this).reduce(pvc.unionExtents,null)},_getContinuousVisibleCellExtent:function(valueAxis,valueDataCell){var valueRole=valueDataCell.role;this._warnSingleContinuousValueRole(valueRole);if(valueRole.name==='series'){throw def.error.notImplemented()}var useAbs=valueAxis.scaleUsesAbs();var data=this.visibleData(valueDataCell.dataPartValue);var extent=data&&data.dimensions(valueRole.firstDimensionName()).extent({abs:useAbs});if(extent){var minValue=extent.min.value;var maxValue=extent.max.value;return{min:(useAbs?Math.abs(minValue):minValue),max:(useAbs?Math.abs(maxValue):maxValue)}}},markEventDefaults:{strokeStyle:"#5BCBF5",lineWidth:"0.5",textStyle:"#5BCBF5",verticalOffset:10,verticalAnchor:"bottom",horizontalAnchor:"right",forceHorizontalAnchor:false,horizontalAnchorSwapLimit:80},markEvent:function(dateString,label,options){var baseScale=this.axes.base.scale;if(baseScale.type!=='timeSeries'){this._log("Attempting to mark an event on a non timeSeries chart");return this}var o=$.extend({},this.markEventDefaults,options);var d=pv.Format.date(this.options.timeSeriesFormat).parse(dateString);var dpos=baseScale(d),range=baseScale.range();if(dposrange[1]){this._log("Event outside the allowed range, returning");return this}var panel=this.plotPanelList[0].pvPanel;var h=this.yScale.range()[1];if(!o.forceHorizontalAnchor){var availableSize=o.horizontalAnchor=="right"?range[1]-dpos:dpos;if(availableSize=5;var margins=new pvc.Sides(0);var paddings=new pvc.Sides(0);var remSize=def.copyOwn(layoutInfo.clientSize);var aolMap=pvc.BasePanel.orthogonalLength;var aoMap=pvc.BasePanel.relativeAnchor;var alMap=pvc.BasePanel.parallelLength;var childKeyArgs={force:true,referenceSize:layoutInfo.clientSize};var fillChildren=[];var sideChildren=[];var paddingHistory={};var LoopDetected=1;var NormalPaddingsChanged=2;var OverflowPaddingsChanged=4;var emptyNewPaddings=new pvc.Sides();var isDisasterRecovery=false;if(useLog){me._group("CCC GRID LAYOUT clientSize = "+pvc.stringify(remSize))}try{this._children.forEach(initChild);if(useLog){me._group("Phase 1 - Determine MARGINS and FILL SIZE from SIDE panels")}try{sideChildren.forEach(layoutChild1Side)}finally{if(useLog){me._groupEnd();me._log("Final FILL margins = "+pvc.stringify(margins));me._log("Final FILL border size = "+pvc.stringify(remSize))}}if(useLog){me._group("Phase 2 - Determine COMMON PADDINGS")}try{doMaxTimes(9,layoutCycle)}finally{if(useLog){me._groupEnd();me._log("Final FILL clientSize = "+pvc.stringify({width:(remSize.width-paddings.width),height:(remSize.height-paddings.height)}));me._log("Final COMMON paddings = "+pvc.stringify(paddings))}}layoutInfo.gridMargins=new pvc.Sides(margins);layoutInfo.gridPaddings=new pvc.Sides(paddings);layoutInfo.gridSize=new pvc.Size(remSize)}finally{if(useLog){me._groupEnd()}}function layoutCycle(remTimes,iteration){if(useLog){me._group("LayoutCycle "+(isDisasterRecovery?"- Disaster MODE":("#"+(iteration+1))))}try{var index,count;var canChange=layoutInfo.canChange!==false&&!isDisasterRecovery&&(remTimes>0);var paddingsChanged;var ownPaddingsChanged=false;var breakAndRepeat;index=0;count=sideChildren.length;while(index0){if(useLog){me._log("SIDE Child #"+(index+1)+" changed normal paddings")}breakAndRepeat=true}else if(pvc.debug>=2){me._warn("SIDE Child #"+(index+1)+" changed paddings but no more iterations possible.")}}if((paddingsChanged&LoopDetected)!==0){isDisasterRecovery=true;layoutCycle(0);return false}if(breakAndRepeat){return true}}}finally{if(useLog){me._groupEnd()}}index++}if(ownPaddingsChanged){if(useLog){me._log("Restarting due to overflowPaddings change")}return false}index=0;count=fillChildren.length;while(index0){if(pvc.debug>=5){me._log("FILL Child #"+(index+1)+" increased paddings")}breakAndRepeat=true}else if(pvc.debug>=2){me._warn("FILL Child #"+(index+1)+" increased paddings but no more iterations possible.")}}if((paddingsChanged&LoopDetected)!==0){isDisasterRecovery=true;layoutCycle(0);return false}if(breakAndRepeat){return true}}}finally{if(useLog){me._groupEnd()}}index++}return false}finally{if(useLog){me._groupEnd()}}}function doMaxTimes(maxTimes,fun){var index=0;while(maxTimes--){if(fun(maxTimes,index)===false){return true}index++}return false}function initChild(child){var a=child.anchor;if(a){if(a==='fill'){fillChildren.push(child);var childPaddings=child.paddings.resolve(childKeyArgs.referenceSize);paddings=pvc.Sides.resolvedMax(paddings,childPaddings)}else{def.hasOwn(aoMap,a)||def.fail.operationInvalid("Unknown anchor value '{0}'",[a]);sideChildren.push(child)}}}function layoutChild1Side(child,index){if(useLog){me._group("SIDE Child #"+(index+1))}try{var paddingsChanged=0;var a=child.anchor;childKeyArgs.paddings=filterAnchorPaddings(a,paddings);child.layout(new pvc.Size(remSize),childKeyArgs);if(child.isVisible){paddingsChanged|=checkAnchorPaddingsChanged(a,paddings,child);positionChildNormal(a,child);updateSide(a,child)}return paddingsChanged}finally{if(useLog){me._groupEnd()}}}function layoutChildFill(child,canChange){var paddingsChanged=0;var a=child.anchor;childKeyArgs.paddings=filterAnchorPaddings(a,paddings);childKeyArgs.canChange=canChange;child.layout(new pvc.Size(remSize),childKeyArgs);if(child.isVisible){paddingsChanged|=checkAnchorPaddingsChanged(a,paddings,child,canChange);positionChildNormal(a,child);positionChildOrtho(child,a)}return paddingsChanged}function layoutChild2Side(child,canChange){var paddingsChanged=0;if(child.isVisible){var a=child.anchor;var al=alMap[a];var aol=aolMap[a];var length=remSize[al];var olength=child[aol];var childSize2=new pvc.Size(def.set({},al,length,aol,olength));childKeyArgs.paddings=filterAnchorPaddings(a,paddings);childKeyArgs.canChange=canChange;child.layout(childSize2,childKeyArgs);if(child.isVisible){paddingsChanged=checkAnchorPaddingsChanged(a,paddings,child,canChange)|checkOverflowPaddingsChanged(a,layoutInfo.paddings,child,canChange);if(!paddingsChanged){positionChildOrtho(child,child.align)}}}return paddingsChanged}function positionChildNormal(side,child){var sidePos;if(side==='fill'){side='left';sidePos=margins.left+remSize.width/2-(child.width/2)}else{sidePos=margins[side]}child.setPosition(def.set({},side,sidePos))}function updateSide(side,child){var sideol=aolMap[side],olen=child[sideol];margins[side]+=olen;remSize[sideol]-=olen}function positionChildOrtho(child,align){var sideo;if(align==='fill'){align='middle'}var sideOPos;switch(align){case'top':case'bottom':case'left':case'right':sideo=align;sideOPos=margins[sideo];break;case'middle':sideo='bottom';sideOPos=margins.bottom+(remSize.height/2)-(child.height/2);break;case'center':sideo='left';sideOPos=margins.left+remSize.width/2-(child.width/2);break}child.setPosition(def.set({},sideo,sideOPos))}function filterAnchorPaddings(a,paddings){var filtered=new pvc.Sides();getAnchorPaddingsNames(a).forEach(function(side){filtered.set(side,paddings[side])});return filtered}function checkAnchorPaddingsChanged(a,paddings,child,canChange){var newPaddings=child._layoutInfo.requestPaddings;var changed=0;if(newPaddings){if(useLog&&pvc.debug>=10){me._log("=> clientSize="+pvc.stringify(child._layoutInfo.clientSize));me._log("<= requestPaddings="+pvc.stringify(newPaddings))}getAnchorPaddingsNames(a).forEach(function(side){var value=paddings[side]||0;var newValue=Math.floor(10000*(newPaddings[side]||0))/10000;var increase=newValue-value;var minChange=Math.max(1,Math.abs(0.01*value));if(increase!==0&&Math.abs(increase)>=minChange){if(!canChange){if(pvc.debug>=2){me._warn("CANNOT change but child wanted to: "+side+"="+newValue)}}else{changed|=NormalPaddingsChanged;paddings[side]=newValue;if(useLog){me._log("Changed padding "+side+" <- "+newValue)}}}});if(changed){var paddingKey=pvc.Sides.names.map(function(side){return(paddings[side]||0).toFixed(0)}).join('|');if(def.hasOwn(paddingHistory,paddingKey)){if(pvc.debug>=2){me._warn("LOOP detected!!!!")}changed|=LoopDetected}else{paddingHistory[paddingKey]=true}paddings.width=paddings.left+paddings.right;paddings.height=paddings.top+paddings.bottom}}return changed}function checkOverflowPaddingsChanged(a,ownPaddings,child,canChange){var overflowPaddings=child._layoutInfo.overflowPaddings||emptyNewPaddings;var changed=0;if(useLog&&pvc.debug>=10){me._log("<= overflowPaddings="+pvc.stringify(overflowPaddings))}getAnchorPaddingsNames(a).forEach(function(side){if(overflowPaddings.hasOwnProperty(side)){var value=ownPaddings[side]||0;var newValue=Math.floor(10000*(overflowPaddings[side]||0))/10000;newValue-=margins[side];var increase=newValue-value;var minChange=Math.max(1,Math.abs(0.05*value));if(increase>=minChange){if(!canChange){if(pvc.debug>=2){me._warn("CANNOT change overflow padding but child wanted to: "+side+"="+newValue)}}else{changed|=OverflowPaddingsChanged;ownPaddings[side]=newValue;if(useLog){me._log("changed overflow padding "+side+" <- "+newValue)}}}}});if(changed){ownPaddings.width=ownPaddings.left+ownPaddings.right;ownPaddings.height=ownPaddings.top+ownPaddings.bottom}return changed}function getAnchorPaddingsNames(a){switch(a){case'left':case'right':return pvc.Sides.vnames;case'top':case'bottom':return pvc.Sides.hnames;case'fill':return pvc.Sides.names}}}}); -def.type('pvc.CartesianGridDockingPanel',pvc.GridDockingPanel).init(function(chart,parent,options){this.base(chart,parent,options);this._plotBgPanel=new pvc.PlotBgPanel(chart,this)}).add({_getExtensionId:function(){return!this.chart.parent?'content':'smallContent'},_createCore:function(layoutInfo){var chart=this.chart;var axes=chart.axes;var xAxis=axes.x;var yAxis=axes.y;if(xAxis.option('Visible')&&xAxis.option('Grid')){this.xGridRule=this._createGridRule(xAxis)}if(yAxis.option('Visible')&&yAxis.option('Grid')){this.yGridRule=this._createGridRule(yAxis)}this.base(layoutInfo);if(chart.focusWindow){this._createFocusWindow(layoutInfo)}var plotFrameVisible;if(chart.compatVersion()<=1){plotFrameVisible=!!(xAxis.option('EndLine')||yAxis.option('EndLine'))}else{plotFrameVisible=def.get(chart.options,'plotFrameVisible',true)}if(plotFrameVisible){this.pvFrameBar=this._createFrame(layoutInfo,axes)}if(xAxis.scaleType!=='discrete'&&xAxis.option('ZeroLine')){this.xZeroLine=this._createZeroLine(xAxis,layoutInfo)}if(yAxis.scaleType!=='discrete'&&yAxis.option('ZeroLine')){this.yZeroLine=this._createZeroLine(yAxis,layoutInfo)}},_createGridRule:function(axis){var scale=axis.scale;if(scale.isNull){return}var isDiscrete=axis.role.grouping.isDiscrete();var axisPanel=this.chart.axesPanels[axis.id];var rootScene=axisPanel._getRootScene();if(!rootScene){return}var margins=this._layoutInfo.gridMargins;var paddings=this._layoutInfo.gridPaddings;var tick_a=axis.orientation==='x'?'left':'bottom';var len_a=this.anchorLength(tick_a);var obeg_a=this.anchorOrtho(tick_a);var oend_a=this.anchorOpposite(obeg_a);var tick_offset=margins[tick_a]+paddings[tick_a];var obeg=margins[obeg_a];var oend=margins[oend_a];var tickScenes=rootScene.leafs().array();var tickCount=tickScenes.length;if(isDiscrete&&tickCount){tickScenes.push(tickScenes[tickCount-1])}var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(tickScene){return v1f.call(this,tickScene.vars.tick.rawValue)}}}var pvGridRule=new pvc.visual.Rule(this,this.pvPanel,{extensionId:axis.extensionPrefixes.map(function(prefix){return prefix+'Grid'}),wrapper:wrapper}).lock('data',tickScenes).lock(len_a,null).override('defaultColor',function(){return pv.color("#f0f0f0")}).pvMark.lineWidth(1).antialias(true)[obeg_a](obeg)[oend_a](oend).zOrder(-12).events('none');if(isDiscrete){var halfStep=scale.range().step/2;pvGridRule.lock(tick_a,function(tickScene){var tickPosition=tick_offset+scale(tickScene.vars.tick.value);var isLastLine=this.index===tickCount;return tickPosition+(isLastLine?halfStep:-halfStep)})}else{pvGridRule.lock(tick_a,function(tickScene){return tick_offset+scale(tickScene.vars.tick.value)})}return pvGridRule},_createFrame:function(layoutInfo,axes){if(axes.base.scale.isNull||(axes.ortho.scale.isNull&&(!axes.ortho2||axes.ortho2.scale.isNull))){return}var margins=layoutInfo.gridMargins;var left=margins.left;var right=margins.right;var top=margins.top;var bottom=margins.bottom;var extensionIds=[];if(this.compatVersion()<=1){extensionIds.push('xAxisEndLine');extensionIds.push('yAxisEndLine')}extensionIds.push('plotFrame');return new pvc.visual.Panel(this,this.pvPanel,{extensionId:extensionIds}).pvMark.lock('left',left).lock('right',right).lock('top',top).lock('bottom',bottom).lock('fillStyle',null).events('none').strokeStyle("#666666").lineWidth(1).antialias(false).zOrder(-8)},_createZeroLine:function(axis,layoutInfo){var scale=axis.scale;if(!scale.isNull){var domain=scale.domain();if(domain[0]*domain[1]<-1e-12){var a=axis.orientation==='x'?'left':'bottom';var len_a=this.anchorLength(a);var obeg_a=this.anchorOrtho(a);var oend_a=this.anchorOpposite(obeg_a);var margins=layoutInfo.gridMargins;var paddings=layoutInfo.gridPaddings;var zeroPosition=margins[a]+paddings[a]+scale(0);var obeg=margins[obeg_a];var oend=margins[oend_a];var rootScene=new pvc.visual.Scene(null,{panel:this});return new pvc.visual.Rule(this,this.pvPanel,{extensionId:axis.extensionPrefixes.map(function(prefix){return prefix+'ZeroLine'})}).lock('data',[rootScene]).lock(len_a,null).lock(obeg_a,obeg).lock(oend_a,oend).lock(a,zeroPosition).override('defaultColor',function(){return pv.color("#666666")}).pvMark.events('none').lineWidth(1).antialias(true).zOrder(-9)}}},_createFocusWindow:function(layoutInfo){var me=this;var topRoot=me.topRoot;var chart=me.chart;var focusWindow=chart.focusWindow.base;var axis=focusWindow.axis;var scale=axis.scale;if(scale.isNull){return}var resizable=focusWindow.option('Resizable');var movable=focusWindow.option('Movable');var isDiscrete=axis.isDiscrete();var isV=chart.isOrientationVertical();var a_left=isV?'left':'top';var a_top=isV?'top':'left';var a_width=me.anchorOrthoLength(a_left);var a_right=me.anchorOpposite(a_left);var a_height=me.anchorOrthoLength(a_top);var a_bottom=me.anchorOpposite(a_top);var a_x=isV?'x':'y';var a_dx='d'+a_x;var a_y=isV?'y':'x';var a_dy='d'+a_y;var margins=layoutInfo.gridMargins;var paddings=layoutInfo.gridPaddings;var space={left:margins.left+paddings.left,right:margins.right+paddings.right,top:margins.top+paddings.top,bottom:margins.bottom+paddings.bottom};space.width=space.left+space.right;space.height=space.top+space.bottom;var clientSize=layoutInfo.clientSize;var wf=clientSize[a_width];var hf=clientSize[a_height];var w=wf-space[a_width];var h=hf-space[a_height];var padLeft=paddings[a_left];var padRight=paddings[a_right];var scene=new pvc.visual.Scene(null,{panel:this});var band=isDiscrete?scale.range().step:0;var halfBand=band/2;scene[a_x]=scale(focusWindow.begin)-halfBand,scene[a_dx]=band+(scale(focusWindow.end)-halfBand)-scene[a_x],resetSceneY();function resetSceneY(){scene[a_y]=0-paddings[a_top];scene[a_dy]=h+paddings[a_top]+paddings[a_bottom]}var sceneProp=function(p){return function(){return scene[p]}};var boundLeft=function(){var begin=scene[a_x];return Math.max(0,Math.min(w,begin))};var boundWidth=function(){var begin=boundLeft();var end=scene[a_x]+scene[a_dx];end=Math.max(0,Math.min(w,end));return end-begin};var addSelBox=function(panel,id){return new pvc.visual.Bar(me,panel,{extensionId:id,normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true,showsInteraction:false}).pvMark.lock('data').lock('visible').lock(a_left,boundLeft).lock(a_width,boundWidth).lock(a_top,sceneProp(a_y)).lock(a_height,sceneProp(a_dy)).lock(a_bottom).lock(a_right).sign};var baseBgPanel=this._plotBgPanel.pvPanel.borderPanel;baseBgPanel.lock('data',[scene]);if(movable&&resizable){baseBgPanel.paddingPanel.lock('events','all').lock('cursor','crosshair').event('mousedown',pv.Behavior.select().autoRender(false).collapse(isV?'y':'x').positionConstraint(function(drag){var op=drag.phase==='start'?'new':'resize-end';return positionConstraint(drag,op)})).event('selectstart',function(ev){resetSceneY();onDrag(ev)}).event('select',onDrag).event('selectend',onDrag)}else{baseBgPanel.paddingPanel.events('all')}var focusBg=addSelBox(baseBgPanel.paddingPanel,'focusWindowBg').override('defaultColor',function(type){return pvc.invisibleFill}).pvMark;if(movable){focusBg.lock('events','all').lock('cursor','move').event("mousedown",pv.Behavior.drag().autoRender(false).collapse(isV?'y':'x').positionConstraint(function(drag){positionConstraint(drag,'move')})).event("drag",onDrag).event("dragend",onDrag)}else{focusBg.events('none')}var baseFgPanel=new pvc.visual.Panel(me,me.pvPanel).pvMark.lock('data',[scene]).lock('visible').lock('fillStyle',pvc.invisibleFill).lock('left',space.left).lock('right',space.right).lock('top',space.top).lock('bottom',space.bottom).lock('zOrder',10).lock('events',function(){var drag=scene.drag;return drag&&drag.phase!=='end'?'all':'none'}).lock('cursor',function(){var drag=scene.drag;return drag&&drag.phase!=='end'?((drag.type==='drag'||(drag.type==='select'&&!resizable))?'move':(isV?'ew-resize':'ns-resize')):null}).antialias(false);var curtainFillColor='rgba(20, 20, 20, 0.1)';new pvc.visual.Bar(me,baseFgPanel,{extensionId:'focusWindowBaseCurtain',normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true,showsInteraction:false}).override('defaultColor',function(type){return type==='stroke'?null:curtainFillColor}).pvMark.lock('data',[scene,scene]).lock('visible').lock('events','none').lock(a_left,function(){return!this.index?-padLeft:boundLeft()+boundWidth()}).lock(a_right,function(){return!this.index?null:-padRight}).lock(a_width,function(){return!this.index?padLeft+boundLeft():null}).lock(a_top,sceneProp(a_y)).lock(a_height,sceneProp(a_dy)).lock(a_bottom);var selectBoxFg=addSelBox(baseFgPanel,'focusWindow').override('defaultColor',function(type){return null}).pvMark.lock('events','none');var addResizeSideGrip=function(side){var a_begin=(side==='left'||side==='top')?'begin':'end';var opposite=me.anchorOpposite(side);var fillColor='linear-gradient(to '+opposite+', '+curtainFillColor+', #444 90%)';var grip=new pvc.visual.Bar(me,selectBoxFg.anchor(side),{extensionId:focusWindow.id+'Grip'+def.firstUpperCase(a_begin),normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true,showsInteraction:false}).override('defaultColor',function(type){return type==='stroke'?null:fillColor}).pvMark.lock('data').lock('visible')[a_top](scene[a_y])[a_height](scene[a_dy]);if(resizable){var opId='resize-'+a_begin;grip.lock('events','all')[a_width](5).cursor(isV?'ew-resize':'ns-resize').event("mousedown",pv.Behavior.resize(side).autoRender(false).positionConstraint(function(drag){positionConstraint(drag,opId)}).preserveOrtho(true)).event("resize",onDrag).event("resizeend",onDrag)}else{grip.events('none')[a_width](1)}return grip};addResizeSideGrip(a_left);addResizeSideGrip(a_right);function onDrag(){var ev=arguments[arguments.length-1];var isEnd=ev.drag.phase==='end';topRoot._isRubberBandSelecting=!isEnd;baseBgPanel.render();baseFgPanel.render();var pbeg=scene[a_x];var pend=scene[a_x]+scene[a_dx];if(!isV){var temp=w-pbeg;pbeg=w-pend;pend=temp}focusWindow._updatePosition(pbeg,pend,isEnd,true)}var a_p=a_x;var a_dp=a_dx;function positionConstraint(drag,op){var m=drag.m;var p=m[a_p];var b,e,l;var l0=scene[a_dp];var target;switch(op){case'new':l=0;target='begin';break;case'resize-begin':l=l0;target='begin';break;case'move':l=l0;target='begin';break;case'resize-end':l=p-scene[a_p];target='end';break}var min=drag.min[a_p];var max=drag.max[a_p];var oper={type:op,target:target,point:p,length:l,length0:l0,min:min,max:max,minView:0,maxView:w};focusWindow._constraintPosition(oper);m[a_p]=oper.point;switch(op){case'resize-begin':oper.max=Math.min(oper.max,scene[a_p]+scene[a_dp]);break;case'resize-end':oper.min=Math.max(oper.min,scene[a_p]);break}drag.min[a_p]=oper.min;drag.max[a_p]=oper.max}},_getOrthoAxis:function(type){var orthoType=type==='base'?'ortho':'base';return this.chart.axes[orthoType]},_getDatumsOnRect:function(datumMap,rect,keyArgs){var chart=this.chart,xAxisPanel=chart.axesPanels.x,yAxisPanel=chart.axesPanels.y,xDatumMap,yDatumMap;if(xAxisPanel){xDatumMap=new def.Map();xAxisPanel._getDatumsOnRect(xDatumMap,rect,keyArgs);if(!xDatumMap.count){xDatumMap=null}}if(yAxisPanel){yDatumMap=new def.Map();yAxisPanel._getOwnDatumsOnRect(yDatumMap,rect,keyArgs);if(!yDatumMap.count){yDatumMap=null}}if(xDatumMap&&yDatumMap){xDatumMap.intersect(yDatumMap,datumMap);keyArgs.toggle=true}else if(xDatumMap){datumMap.copy(xDatumMap)}else if(yDatumMap){datumMap.copy(yDatumMap)}else{chart.plotPanelList.forEach(function(plotPanel){plotPanel._getDatumsOnRect(datumMap,rect,keyArgs)},this)}}}); -def.type('pvc.CartesianAbstractPanel',pvc.PlotPanel).init(function(chart,parent,plot,options){this.base(chart,parent,plot,options);var axes=this.axes;function addAxis(axis){axes[axis.type]=axis;axes[axis.orientedId]=axis;if(axis.v1SecondOrientedId){axes[axis.v1SecondOrientedId]=axis}}addAxis(chart._getAxis('base',plot.option('BaseAxis')-1));addAxis(chart._getAxis('ortho',plot.option('OrthoAxis')-1));var pctPaddings={};var hasAny=false;function setSide(side,pct){var value=pctPaddings[side];if(value==null||pct>value){hasAny=true;pctPaddings[side]=pct}}function processAxis(axis){var offset=axis&&axis.option('Offset');if(offset!=null&&offset>0&&offset<1){if(axis.orientation==='x'){setSide('left',offset);setSide('right',offset)}else{setSide('top',offset);setSide('bottom',offset)}}}var chartAxes=chart.axesByType;['base','ortho'].forEach(function(type){var typeAxes=chartAxes[type];if(typeAxes){typeAxes.forEach(processAxis)}});if(hasAny){this.offsetPaddings=pctPaddings}}).add({offsetPaddings:null,_calcLayout:function(layoutInfo){layoutInfo.requestPaddings=this._calcRequestPaddings(layoutInfo)},_calcRequestPaddings:function(layoutInfo){var reqPads;var offPads=this.offsetPaddings;if(offPads){var tickRoundPads=this.chart._getAxesRoundingPaddings();var clientSize=layoutInfo.clientSize;var pads=layoutInfo.paddings;pvc.Sides.names.forEach(function(side){var len_a=pvc.BasePanel.orthogonalLength[side];var clientLen=clientSize[len_a];var paddingLen=pads[len_a];var len=clientLen+paddingLen;if(!tickRoundPads[side+'Locked']){var offLen=len*(offPads[side]||0);var roundLen=clientLen*(tickRoundPads[side]||0);(reqPads||(reqPads={}))[side]=Math.max(offLen-roundLen,0)}},this)}return reqPads},_createCore:function(){this.pvPanel.zOrder(-10);var hideOverflow;var contentOverflow=this.chart.options.leafContentOverflow||'auto';if(contentOverflow==='auto'){hideOverflow=def.query(['ortho','base']).select(function(axisType){return this.axes[axisType]},this).any(function(axis){return axis.option('FixedMin')!=null||axis.option('FixedMax')!=null})}else{hideOverflow=(contentOverflow==='hidden')}if(hideOverflow){this.pvPanel.borderPanel.overflow('hidden')}}}); -def.type('pvc.PlotBgPanel',pvc.BasePanel).init(function(chart,parent,options){this.base(chart,parent,options)}).add({anchor:'fill',_getExtensionId:function(){return'plotBg'},_createCore:function(layoutInfo){this.pvPanel.borderPanel.lock('zOrder',-13).antialias(false);this.base(layoutInfo)}}); -def.type('pvc.CategoricalAbstract',pvc.CartesianAbstract).init(function(options){this.base(options);var parent=this.parent;if(parent){this._catRole=parent._catRole}}).add({_initVisualRoles:function(){this.base();this._catRole=this._addVisualRole('category',this._getCategoryRoleSpec())},_getCategoryRoleSpec:function(){return{isRequired:true,defaultDimension:'category*',autoCreateDimension:true}},_generateTrendsDataCellCore:function(newDatums,dataCell,trendInfo){var serRole=this._serRole;var xRole=this._catRole;var yRole=dataCell.role;var trendOptions=dataCell.trend;this._warnSingleContinuousValueRole(yRole);var dataPartDimName=this._dataPartRole.firstDimensionName();var yDimName=yRole.firstDimensionName();var xDimName;var isXDiscrete=xRole.isDiscrete();if(!isXDiscrete){xDimName=xRole.firstDimensionName()}var sumKeyArgs={zeroIfNone:false};var ignoreNullsKeyArgs={ignoreNulls:false};var data=this.visibleData(dataCell.dataPartValue);var allPartsData=this.visibleData(null,ignoreNullsKeyArgs);var allCatDataRoot=allPartsData.flattenBy(xRole,ignoreNullsKeyArgs);var allCatDatas=allCatDataRoot._children;def.scope(function(){return(serRole&&serRole.isBound())?data.flattenBy(serRole).children():def.query([null])}).each(genSeriesTrend,this);function genSeriesTrend(serData1){var funX=isXDiscrete?null:function(allCatData){return allCatData.atoms[xDimName].value};var funY=function(allCatData){var group=data._childrenByKey[allCatData.key];if(group&&serData1){group=group._childrenByKey[serData1.key]}return group?group.dimensions(yDimName).sum(sumKeyArgs):null};var options=def.create(trendOptions,{rows:def.query(allCatDatas),x:funX,y:funY});var trendModel=trendInfo.model(options);var dataPartAtom=data.owner.dimensions(dataPartDimName).intern(this.root._firstTrendAtomProto);if(trendModel){allCatDatas.forEach(function(allCatData,index){var trendX=isXDiscrete?index:allCatData.atoms[xDimName].value;var trendY=trendModel.sample(trendX,funY(allCatData),index);if(trendY!=null){var catData=data._childrenByKey[allCatData.key];var efCatData=catData||allCatData;var atoms;if(serData1){var catSerData=catData&&catData._childrenByKey[serData1.key];if(catSerData){atoms=Object.create(catSerData._datums[0].atoms)}else{atoms=Object.create(efCatData._datums[0].atoms);def.copyOwn(atoms,serData1.atoms)}}else{atoms=Object.create(efCatData._datums[0].atoms)}atoms[yDimName]=trendY;atoms[dataPartDimName]=dataPartAtom;var newDatum=new pvc.data.Datum(efCatData.owner,atoms);newDatum.isVirtual=true;newDatum.isTrend=true;newDatum.trendType=trendInfo.type;newDatums.push(newDatum)}},this)}}},_interpolateDataCell:function(dataCell){var nullInterpMode=dataCell.nullInterpolationMode;if(nullInterpMode){var InterpType;switch(dataCell.nullInterpolationMode){case'linear':InterpType=pvc.data.LinearInterpolationOper;break;case'zero':InterpType=pvc.data.ZeroInterpolationOper;break;case'none':break;default:throw def.error.argumentInvalid('nullInterpolationMode',''+nullInterpMode)}if(InterpType){this._warnSingleContinuousValueRole(dataCell.role);var visibleData=this.visibleData(dataCell.dataPartValue);if(visibleData.childCount()>0){var allPartsData=this.visibleData(null,{ignoreNulls:false});new InterpType(allPartsData,visibleData,this._catRole,this._serRole,dataCell.role,true).interpolate()}}}},_createVisibleData:function(dataPartValue,keyArgs){var serGrouping=this._serRole&&this._serRole.flattenedGrouping();var catGrouping=this._catRole.flattenedGrouping();var partData=this.partData(dataPartValue);var ignoreNulls=def.get(keyArgs,'ignoreNulls');var groupKeyArgs={visible:true,isNull:ignoreNulls?false:null};return serGrouping?partData.groupBy([catGrouping,serGrouping],groupKeyArgs):partData.groupBy(catGrouping,groupKeyArgs)},_getContinuousVisibleCellExtent:function(valueAxis,valueDataCell){var valueRole=valueDataCell.role;switch(valueRole.name){case'series':case'category':return this.base(valueAxis,valueDataCell)}this._warnSingleContinuousValueRole(valueRole);var dataPartValue=valueDataCell.dataPartValue;var valueDimName=valueRole.firstDimensionName();var data=this.visibleData(dataPartValue);var useAbs=valueAxis.scaleUsesAbs();if(valueAxis.type!=='ortho'||!valueDataCell.isStacked){return data.leafs().select(function(serGroup){var value=serGroup.dimensions(valueDimName).sum();return useAbs&&value<0?-value:value}).range()}return data.children().select(function(catGroup){var range=this._getStackedCategoryValueExtent(catGroup,valueDimName,useAbs);if(range){return{range:range,group:catGroup}}},this).where(def.notNully).reduce(function(result,rangeInfo){return this._reduceStackedCategoryValueExtent(result,rangeInfo.range,rangeInfo.group)}.bind(this),null)},_getStackedCategoryValueExtent:function(catGroup,valueDimName,useAbs){var posSum=null,negSum=null;catGroup.children().select(function(serGroup){var value=serGroup.dimensions(valueDimName).sum();return useAbs&&value<0?-value:value}).each(function(value){if(value!=null){if(value>=0){posSum+=value}else{negSum+=value}}});if(posSum==null&&negSum==null){return null}return{max:posSum||0,min:negSum||0}},_reduceStackedCategoryValueExtent:function(result,catRange,catGroup){return pvc.unionExtents(result,catRange)},_coordinateSmallChartsLayout:function(scopesByType){this.base(scopesByType);var titleSizeMax=0;var titleOrthoLen;var axisIds=null;var sizesMaxByAxisId={};this.children.forEach(function(childChart){childChart.basePanel.layout();var size;var panel=childChart.titlePanel;if(panel){if(!titleOrthoLen){titleOrthoLen=panel.anchorOrthoLength()}size=panel[titleOrthoLen];if(size>titleSizeMax){titleSizeMax=size}}var axesPanels=childChart.axesPanels;if(!axisIds){axisIds=def.query(def.ownKeys(axesPanels)).where(function(alias){return alias===axesPanels[alias].axis.id}).select(function(id){sizesMaxByAxisId[id]={axis:0,title:0};return id}).array()}axisIds.forEach(function(id){var axisPanel=axesPanels[id];var sizes=sizesMaxByAxisId[id];var ol=axisPanel.axis.orientation==='x'?'height':'width';size=axisPanel[ol];if(size>sizes.axis){sizes.axis=size}var titlePanel=axisPanel.titlePanel;if(titlePanel){size=titlePanel[ol];if(size>sizes.title){sizes.title=size}}})},this);this.children.forEach(function(childChart){if(titleSizeMax>0){var panel=childChart.titlePanel;panel.size=panel.size.clone().set(titleOrthoLen,titleSizeMax)}var axesPanels=childChart.axesPanels;axisIds.forEach(function(id){var axisPanel=axesPanels[id];var sizes=sizesMaxByAxisId[id];var ol=axisPanel.axis.orientation==='x'?'height':'width';axisPanel.size=axisPanel.size.clone().set(ol,sizes.axis);var titlePanel=axisPanel.titlePanel;if(titlePanel){titlePanel.size=titlePanel.size.clone().set(ol,sizes.title)}});childChart.basePanel.invalidateLayout()},this)},defaults:{orthoAxisOrdinal:false}}); -def.type('pvc.CategoricalAbstractPanel',pvc.CartesianAbstractPanel).init(function(chart,parent,plot,options){this.base(chart,parent,plot,options);this.stacked=plot.option('Stacked')}); -def.type('pvc.AxisPanel',pvc.BasePanel).init(function(chart,parent,axis,options){options=def.create(options,{anchor:axis.option('Position')});var anchor=options.anchor||this.anchor;this.axis=axis;this.base(chart,parent,options);this.roleName=axis.role.name;this.isDiscrete=axis.role.isDiscrete();this._extensionPrefix=axis.extensionPrefixes;if(this.labelSpacingMin==null){this.labelSpacingMin=this.isDiscrete?0.1:1.5}if(this.showTicks==null){this.showTicks=!this.isDiscrete}if(options.font===undefined){var extFont=this._getConstantExtension('label','font');if(extFont){this.font=extFont}}if(options.tickLength===undefined){var tickLength=+this._getConstantExtension('ticks',this.anchorOrthoLength(anchor));if(!isNaN(tickLength)&&isFinite(tickLength)){this.tickLength=tickLength}}}).add({pvRule:null,pvTicks:null,pvLabel:null,pvRuleGrid:null,pvScale:null,isDiscrete:false,roleName:null,axis:null,anchor:"bottom",tickLength:6,scale:null,ruleCrossesMargin:true,font:'9px sans-serif',labelSpacingMin:null,domainRoundMode:'none',desiredTickCount:null,tickExponentMin:null,tickExponentMax:null,showMinorTicks:true,showTicks:null,hiddenLabelText:"\u00B7",_isScaleSetup:false,_createLogInstanceId:function(){return this.base()+" - "+this.axis.id},getTicks:function(){return this._layoutInfo&&this._layoutInfo.ticks},_calcLayout:function(layoutInfo){var scale=this.axis.scale;if(!this._isScaleSetup){this.pvScale=scale;this.scale=scale;this.extend(scale,"scale");this._isScaleSetup=true}if(scale.isNull){layoutInfo.axisSize=0}else{this._calcLayoutCore(layoutInfo)}return this.createAnchoredSize(layoutInfo.axisSize,layoutInfo.clientSize)},_calcLayoutCore:function(layoutInfo){var axisSize=layoutInfo.desiredClientSize[this.anchorOrthoLength()];layoutInfo.axisSize=axisSize;if(this.isDiscrete&&this.useCompositeAxis){if(layoutInfo.axisSize==null){layoutInfo.axisSize=50}}else{layoutInfo.textAngle=def.number.as(this._getExtension('label','textAngle'),0);layoutInfo.textMargin=def.number.as(this._getExtension('label','textMargin'),3);this._calcTicks();if(this.scale.type==='discrete'){this._calcDiscreteTicksHidden()}this._calcAxisSizeFromLabel();if(layoutInfo.axisSize==null){layoutInfo.axisSize=layoutInfo.requiredAxisSize}this._calcMaxTextLengthThatFits();this._calcOverflowPaddings()}},_calcAxisSizeFromLabel:function(){this._calcLabelBBox();this._calcAxisSizeFromLabelBBox()},_calcLabelBBox:function(){var layoutInfo=this._layoutInfo;var align=this._getExtension('label','textAlign');if(typeof align!=='string'){align=this.isAnchorTopOrBottom()?"center":(this.anchor=="left")?"right":"left"}var baseline=this._getExtension('label','textBaseline');if(typeof baseline!=='string'){switch(this.anchor){case"right":case"left":case"center":baseline="middle";break;case"bottom":baseline="top";break;default:baseline="bottom"}}return(layoutInfo.labelBBox=pvc.text.getLabelBBox(layoutInfo.maxTextWidth!=null?layoutInfo.maxTextWidth:layoutInfo._maxTextWidth,layoutInfo.textHeight,align,baseline,layoutInfo.textAngle,layoutInfo.textMargin))},_calcAxisSizeFromLabelBBox:function(){var layoutInfo=this._layoutInfo;var labelBBox=layoutInfo.labelBBox;var length=this._getLabelBBoxQuadrantLength(labelBBox,this.anchor);var axisSize=this.tickLength+length;var angle=labelBBox.sourceAngle;if(!(angle===0&&this.isAnchorTopOrBottom())){axisSize+=this.tickLength}layoutInfo.requiredAxisSize=axisSize},_getLabelBBoxQuadrantLength:function(labelBBox,quadrantSide){var length;switch(quadrantSide){case'left':length=-labelBBox.x;break;case'right':length=labelBBox.x2;break;case'top':length=-labelBBox.y;break;case'bottom':length=labelBBox.y2;break}return Math.max(length,0)},_calcOverflowPaddings:function(){if(!this._layoutInfo.canChange){if(pvc.debug>=2){this._log("[WARNING] Layout cannot change. Skipping calculation of overflow paddings.")}return}if(!this._layoutInfo.labelBBox){this._calcLabelBBox()}this._calcOverflowPaddingsFromLabelBBox()},_calcOverflowPaddingsFromLabelBBox:function(){var overflowPaddings=null;var layoutInfo=this._layoutInfo;var ticks=layoutInfo.ticks;var tickCount=ticks.length;if(tickCount){var paddings=layoutInfo.paddings;var labelBBox=layoutInfo.labelBBox;var isTopOrBottom=this.isAnchorTopOrBottom();var begSide=isTopOrBottom?'left':'top';var endSide=isTopOrBottom?'right':'bottom';var isDiscrete=this.scale.type==='discrete';var clientLength=layoutInfo.clientSize[this.anchorLength()];this.axis.setScaleRange(clientLength);var sideTickOffset;if(isDiscrete){var halfBand=this.scale.range().step/2; sideTickOffset=def.set({},begSide,halfBand,endSide,halfBand)}else{sideTickOffset=def.set({},begSide,this.scale(ticks[0]),endSide,clientLength-this.scale(ticks[tickCount-1]))}[begSide,endSide].forEach(function(side){var overflowPadding=this._getLabelBBoxQuadrantLength(labelBBox,side);if(overflowPadding>0){overflowPadding-=(paddings[side]||0);if(overflowPadding>0){overflowPadding-=sideTickOffset[side];if(overflowPadding>1){if(isDiscrete){overflowPadding*=1.05}if(!overflowPaddings){overflowPaddings={}}overflowPaddings[side]=overflowPadding}}}},this);if(pvc.debug>=6&&overflowPaddings){this._log("OverflowPaddings = "+pvc.stringify(overflowPaddings))}}layoutInfo.overflowPaddings=overflowPaddings},_calcMaxTextLengthThatFits:function(){var layoutInfo=this._layoutInfo;if(this.compatVersion()<=1){layoutInfo.maxTextWidth=null;return}var availableClientLength=layoutInfo.clientSize[this.anchorOrthoLength()];var efSize=Math.min(layoutInfo.axisSize,availableClientLength);if(efSize>=(layoutInfo.requiredAxisSize-this.tickLength)){layoutInfo.maxTextWidth=null}else{var labelBBox=layoutInfo.labelBBox;var maxOrthoLength=efSize-2*this.tickLength;var mostOrthoDistantPoint;var parallelDirection;switch(this.anchor){case'left':parallelDirection=pv.vector(0,1);mostOrthoDistantPoint=pv.vector(-maxOrthoLength,0);break;case'right':parallelDirection=pv.vector(0,1);mostOrthoDistantPoint=pv.vector(maxOrthoLength,0);break;case'top':parallelDirection=pv.vector(1,0);mostOrthoDistantPoint=pv.vector(0,-maxOrthoLength);break;case'bottom':parallelDirection=pv.vector(1,0);mostOrthoDistantPoint=pv.vector(0,maxOrthoLength);break}var orthoOutwardsDir=mostOrthoDistantPoint.norm();var corners=labelBBox.source.points();var botL=corners[0];var botR=corners[1];var topR=corners[2];var topL=corners[3];var topLRSideDir=topR.minus(topL);var botLRSideDir=botR.minus(botL);var intersect=pv.SvgScene.lineIntersect;var botI=intersect(mostOrthoDistantPoint,parallelDirection,botL,botLRSideDir);var topI=intersect(mostOrthoDistantPoint,parallelDirection,topL,topLRSideDir);var sideLRWidth=labelBBox.sourceTextWidth;var maxTextWidth=sideLRWidth;var botLI=botI.minus(botL);var botLILen=botLI.length();if(botLILen<=sideLRWidth&&botLI.dot(topLRSideDir)>=0){if(botL.dot(orthoOutwardsDir)=0){if(topL.dot(orthoOutwardsDir)=3){this._log("Trimming labels' text at length "+maxTextWidth.toFixed(2)+"px maxOrthoLength="+maxOrthoLength.toFixed(2)+"px")}}},_calcTicks:function(){var layoutInfo=this._layoutInfo;layoutInfo.textHeight=pv.Text.fontHeight(this.font);layoutInfo.maxTextWidth=null;this.axis.setTicks(null);switch(this.scale.type){case'discrete':this._calcDiscreteTicks();break;case'timeSeries':this._calcTimeSeriesTicks();break;case'numeric':this._calcNumberTicks(layoutInfo);break;default:throw def.error.operationInvalid("Undefined axis scale type")}this.axis.setTicks(layoutInfo.ticks);var clientLength=layoutInfo.clientSize[this.anchorLength()];this.axis.setScaleRange(clientLength);if(layoutInfo.maxTextWidth==null){layoutInfo.maxTextWidth=def.query(layoutInfo.ticksText).select(function(text){return pv.Text.measure(text,this.font).width},this).max()}layoutInfo._maxTextWidth=layoutInfo.maxTextWidth},_calcDiscreteTicks:function(){var layoutInfo=this._layoutInfo;var role=this.chart.visualRoles(this.roleName);var data=role.flatten(this.chart.data,{visible:true});layoutInfo.data=data;layoutInfo.ticks=data._children;var format,dimType;var grouping=role.grouping;if(grouping.isSingleDimension&&(dimType=grouping.firstDimensionType())&&(dimType.valueType===Date)){var extent=data.dimensions(dimType.name).extent();if(extent&&extent.min!==extent.max){var scale=new pv.Scale.linear(extent.min.value,extent.max.value);scale.ticks();var tickFormatter=this.axis.option('TickFormatter');if(tickFormatter){scale.tickFormatter(tickFormatter)}format=function(child){return scale.tickFormat(child.value)}}}if(!format){format=function(child){return child.absLabel}}layoutInfo.ticksText=data._children.map(format)},_calcTimeSeriesTicks:function(){this._calcContinuousTicks(this._layoutInfo)},_calcNumberTicks:function(){var desiredTickCount=this.desiredTickCount;if(desiredTickCount==null){if(this.isAnchorTopOrBottom()){this._calcNumberHTicks();return}desiredTickCount=this._calcNumberVDesiredTickCount()}this._calcContinuousTicks(this._layoutInfo,desiredTickCount)},_calcContinuousTicks:function(ticksInfo,desiredTickCount){this._calcContinuousTicksValue(ticksInfo,desiredTickCount);this._calcContinuousTicksText(ticksInfo)},_calcContinuousTicksValue:function(ticksInfo,desiredTickCount){ticksInfo.ticks=this.scale.ticks(desiredTickCount,{roundInside:this.domainRoundMode!=='tick',numberExponentMin:this.tickExponentMin,numberExponentMax:this.tickExponentMax});if(pvc.debug>4){this._log("DOMAIN: "+pvc.stringify(this.scale.domain()));this._log("TICKS: "+pvc.stringify(ticksInfo.ticks))}},_calcContinuousTicksText:function(ticksInfo){ticksInfo.ticksText=def.query(ticksInfo.ticks).select(function(tick){return this.scale.tickFormat(tick)},this).array()},_calcDiscreteTicksHidden:function(){return this._tickIncludeModulo=this._calcDiscreteTicksHiddenCore()},_calcDiscreteTicksHiddenCore:function(){var mode=this.axis.option('OverlappedLabelsMode');if(mode!=='hide'){return 1}var layoutInfo=this._layoutInfo;var ticks=layoutInfo.ticks;var tickCount=ticks.length;if(tickCount<=1){return 1}var b=this.scale.range().step;var h=layoutInfo.textHeight;var w=layoutInfo.maxTextWidth;if(!(w>0&&h>0&&b>0)){return 1}var sMin=h*this.labelSpacingMin;var a=layoutInfo.textAngle;var isTopOrBottom=this.isAnchorTopOrBottom();var sinOrCos=isTopOrBottom?'sin':'cos';var cosOrSin=!isTopOrBottom?'sin':'cos';var tickIncludeModulo=1;do{var bEf=tickIncludeModulo*b;var sBase=bEf*Math.abs(Math[sinOrCos](a))-h;var sOrtho=bEf*Math.abs(Math[cosOrSin](a))-w;if(sBase>=sMin||sOrtho>=sMin){break}tickIncludeModulo++}while(Math.ceil(tickCount/tickIncludeModulo)>1);if(tickIncludeModulo>1&&pvc.debug>=3){this._log("Showing only one in every "+tickIncludeModulo+" tick labels")}return tickIncludeModulo},_calcNumberVDesiredTickCount:function(){var layoutInfo=this._layoutInfo;var lineHeight=layoutInfo.textHeight*(1+Math.max(0,this.labelSpacingMin));var clientLength=layoutInfo.clientSize[this.anchorLength()];return Math.max(1,~~(clientLength/lineHeight))},_calcNumberHTicks:function(){var layoutInfo=this._layoutInfo;var clientLength=layoutInfo.clientSize[this.anchorLength()];var spacing=layoutInfo.textHeight*Math.max(0,this.labelSpacingMin);var desiredTickCount=this._calcNumberHDesiredTickCount(spacing);var doLog=(pvc.debug>=7);var dir,prevResultTickCount;var ticksInfo,lastBelow,lastAbove;do{if(doLog){this._log("calculateNumberHTicks TickCount IN desired = "+desiredTickCount)}ticksInfo={};this._calcContinuousTicksValue(ticksInfo,desiredTickCount);var ticks=ticksInfo.ticks;var resultTickCount=ticks.length;if(ticks.exponentOverflow){if(dir==null){if(ticks.exponent===this.exponentMin){lastBelow=ticksInfo;dir=1}else{lastAbove=ticksInfo;dir=-1}}else if(dir===1){if(lastBelow){ticksInfo=lastBelow}break}else{if(lastAbove){ticksInfo=lastAbove}break}}else if(prevResultTickCount==null||resultTickCount!==prevResultTickCount){if(doLog){this._log("calculateNumberHTicks TickCount desired/resulting = "+desiredTickCount+" -> "+resultTickCount)}prevResultTickCount=resultTickCount;this._calcContinuousTicksText(ticksInfo);var length=this._calcNumberHLength(ticksInfo,spacing);var excessLength=ticksInfo.excessLength=length-clientLength;var pctError=ticksInfo.error=Math.abs(excessLength/clientLength);if(doLog){this._log("calculateNumberHTicks error="+(excessLength>=0?"+":"-")+(ticksInfo.error*100).toFixed(0)+"% count="+resultTickCount+" step="+ticks.step);this._log("calculateNumberHTicks Length client/resulting = "+clientLength+" / "+length+" spacing = "+spacing)}if(excessLength>0){if(desiredTickCount===1){if(resultTickCount===3&&pctError<=1){ticksInfo.ticks.splice(1,1);ticksInfo.ticksText.splice(1,1);ticksInfo.ticks.step*=2}else{ticksInfo.ticks.length=1;ticksInfo.ticksText.length=1}delete ticksInfo.maxTextWidth;break}if(lastBelow){ticksInfo=lastBelow;break}lastAbove=ticksInfo;dir=-1}else{if(pctError<=0.05||dir===-1){break}lastBelow=ticksInfo;dir=+1}}desiredTickCount+=dir}while(true);if(ticksInfo){layoutInfo.ticks=ticksInfo.ticks;layoutInfo.ticksText=ticksInfo.ticksText;layoutInfo.maxTextWidth=ticksInfo.maxTextWidth;if(pvc.debug>=5){this._log("calculateNumberHTicks RESULT error="+(ticksInfo.excessLength>=0?"+":"-")+(ticksInfo.error*100).toFixed(0)+"% count="+ticksInfo.ticks.length+" step="+ticksInfo.ticks.step)}}if(doLog){this._log("calculateNumberHTicks END")}},_calcNumberHDesiredTickCount:function(spacing){var layoutInfo=this._layoutInfo;var domainTextLength=this.scale.domain().map(function(tick){tick=+tick.toFixed(2);var text=this.scale.tickFormat(tick);return pv.Text.measure(text,this.font).width},this);var avgTextLength=Math.max((domainTextLength[1]+domainTextLength[0])/2,layoutInfo.textHeight);var clientLength=layoutInfo.clientSize[this.anchorLength()];return Math.max(1,~~(clientLength/(avgTextLength+spacing)))},_calcNumberHLength:function(ticksInfo,spacing){var ticksText=ticksInfo.ticksText;var maxTextWidth=def.query(ticksText).select(function(text){return pv.Text.measure(text,this.font).width},this).max();return Math.max(maxTextWidth,(ticksText.length-1)*(maxTextWidth+spacing))},_createCore:function(){if(this.scale.isNull){return}var clientSize=this._layoutInfo.clientSize;var paddings=this._layoutInfo.paddings;var begin_a=this.anchorOrtho();var end_a=this.anchorOpposite(begin_a);var size_a=this.anchorOrthoLength(begin_a);var rMin=this.ruleCrossesMargin?-paddings[begin_a]:0;var rMax=clientSize[size_a]+(this.ruleCrossesMargin?paddings[end_a]:0);var rSize=rMax-rMin;var ruleParentPanel=this.pvPanel;this._rSize=rSize;var rootScene=this._getRootScene();this.pvRule=new pvc.visual.Rule(this,this.pvPanel,{extensionId:'rule'}).lock('data',[rootScene]).override('defaultColor',def.fun.constant("#666666")).lock(this.anchorOpposite(),0).lock(begin_a,rMin).lock(size_a,rSize).pvMark.zOrder(30).strokeDasharray(null).lineCap('square');if(this.isDiscrete){if(this.useCompositeAxis){this.renderCompositeOrdinalAxis()}else{this.renderOrdinalAxis()}}else{this.renderLinearAxis()}},_getExtensionId:function(){return''},_getRootScene:function(){if(!this._rootScene){var rootScene=this._rootScene=new pvc.visual.CartesianAxisRootScene(null,{panel:this,group:this._getRootData()});var layoutInfo=this._layoutInfo;var ticksText=layoutInfo.ticksText;if(this.isDiscrete){if(this.useCompositeAxis){this._buildCompositeScene(rootScene)}else{layoutInfo.ticks.forEach(function(tickData,index){new pvc.visual.CartesianAxisTickScene(rootScene,{group:tickData,tick:tickData.value,tickRaw:tickData.rawValue,tickLabel:ticksText[index]})})}}else{layoutInfo.ticks.forEach(function(majorTick,index){new pvc.visual.CartesianAxisTickScene(rootScene,{tick:majorTick,tickRaw:majorTick,tickLabel:ticksText[index]})},this)}}return this._rootScene},_buildCompositeScene:function(rootScene){var isV1Compat=this.compatVersion()<=1;rootScene.vars.tick=new pvc.visual.ValueLabelVar('',"");recursive(rootScene);function recursive(scene){var data=scene.group;if(isV1Compat){var tickVar=scene.vars.tick;scene.nodeValue=scene.value=tickVar.rawValue;scene.nodeLabel=scene.label=tickVar.label}if(data.childCount()){data.children().each(function(childData){var childScene=new pvc.visual.CartesianAxisTickScene(scene,{group:childData,tick:childData.value,tickRaw:childData.rawValue,tickLabel:childData.label});recursive(childScene)})}}},_getRootData:function(){var chart=this.chart;var data=chart.data;if(this.isDiscrete&&this.useCompositeAxis){var orientation=this.anchor;var reverse=orientation=='bottom'||orientation=='left';data=chart.visualRoles(this.roleName).select(data,{visible:true,reverse:reverse})}return data},_getOrthoScale:function(){var orthoType=this.axis.type==='base'?'ortho':'base';return this.chart.axes[orthoType].scale},_getOrthoAxis:function(){var orthoType=this.axis.type==='base'?'ortho':'base';return this.chart.axes[orthoType]},renderOrdinalAxis:function(){var myself=this,scale=this.scale,hiddenLabelText=this.hiddenLabelText,anchorOpposite=this.anchorOpposite(),anchorLength=this.anchorLength(),anchorOrtho=this.anchorOrtho(),anchorOrthoLength=this.anchorOrthoLength(),layoutInfo=this._layoutInfo,pvRule=this.pvRule,ticks=layoutInfo.ticks,data=layoutInfo.data,itemCount=layoutInfo.ticks.length,rootScene=this._getRootScene(),includeModulo=this._tickIncludeModulo,isV1Compat=this.compatVersion()<=1;rootScene.vars.tickIncludeModulo=includeModulo;rootScene.vars.hiddenLabelText=hiddenLabelText;var wrapper;if(isV1Compat){var DataElement=function(tickVar){this.value=this.absValue=tickVar.rawValue;this.nodeName=''+(this.value||'');this.path=this.nodeName?[this.nodeName]:[];this.label=this.absLabel=tickVar.label};DataElement.prototype.toString=function(){return''+this.value};wrapper=function(v1f){return function(tickScene){var markWrapped=Object.create(this);markWrapped.index=this.parent.index;return v1f.call(markWrapped,new DataElement(tickScene.vars.tick))}}}var pvTicksPanel=new pvc.visual.Panel(this,this.pvPanel,{extensionId:'ticksPanel'}).lock('data',rootScene.childNodes).localProperty('hidden').lockMark('hidden',function(){return(this.index%includeModulo)!==0}).lock(anchorOpposite,0).lockMark(anchorOrtho,function(tickScene){return scale(tickScene.vars.tick.value)}).lock('strokeDasharray',null).lock('strokeStyle',null).lock('fillStyle',null).lock('lineWidth',0).pvMark.zOrder(20);if(isV1Compat||this.showTicks){var pvTicks=this.pvTicks=new pvc.visual.Rule(this,pvTicksPanel,{extensionId:'ticks',wrapper:wrapper}).lock('data').intercept('visible',function(){return!this.pvMark.parent.hidden()&&this.delegateExtension(true)}).optional('lineWidth',1).lock(anchorOpposite,0).lock(anchorOrtho,0).lock(anchorLength,null).optional(anchorOrthoLength,this.tickLength*2/3).override('defaultColor',function(type){if(isV1Compat){return pv.Color.names.transparent}return pvRule.scene?pvRule.scene[0].strokeStyle:"#666666"}).pvMark}var baseline;var align;switch(this.anchor){case'top':align='center';baseline='bottom';break;case'bottom':align='center';baseline='top';break;case'left':align='right';baseline='middle';break;case'right':align='left';baseline='middle';break}var font=this.font;var maxTextWidth=this._layoutInfo.maxTextWidth;if(!isFinite(maxTextWidth)){maxTextWidth=0}this.pvLabel=new pvc.visual.Label(this,pvTicksPanel,{extensionId:'label',noClick:false,noDoubleClick:false,noSelect:false,noTooltip:false,noHover:false,wrapper:wrapper,tooltipArgs:{buildTooltip:function(context){return context.scene.vars.tick.label},isLazy:false,options:{gravity:this._calcTipsyGravity()}}}).intercept('visible',function(tickScene){return!this.pvMark.parent.hidden()?this.delegateExtension(true):!!tickScene.vars.hiddenLabelText}).intercept('text',function(tickScene){var text;if(this.pvMark.parent.hidden()){text=tickScene.vars.hiddenLabelText}else{text=this.delegateExtension();if(text===undefined){text=tickScene.vars.tick.label}if(maxTextWidth){text=pvc.text.trimToWidthB(maxTextWidth,text,font,"..",false)}}return text}).pvMark.zOrder(40).lock(anchorOpposite,this.tickLength).lock(anchorOrtho,0).font(font).textStyle("#666666").textAlign(align).textBaseline(baseline);this._debugTicksPanel(pvTicksPanel)},_debugTicksPanel:function(pvTicksPanel){if(pvc.debug>=16){var corners=this._layoutInfo.labelBBox.source.points();if(corners.length>1){corners=corners.concat(corners[0])}pvTicksPanel.add(pv.Panel)[this.anchorOpposite()](this.tickLength)[this.anchorOrtho()](0)[this.anchorLength()](0)[this.anchorOrthoLength()](0).fillStyle(null).strokeStyle(null).lineWidth(0).add(pv.Line).visible(function(){var gp=this.parent.parent;return!gp.hidden||!gp.hidden()}).data(corners).left(function(p){return p.x}).top(function(p){return p.y}).strokeStyle('red').lineWidth(0.5).strokeDasharray('-')}},renderLinearAxis:function(){var scale=this.scale,orthoAxis=this._getOrthoAxis(),orthoScale=orthoAxis.scale,pvRule=this.pvRule,anchorOpposite=this.anchorOpposite(),anchorLength=this.anchorLength(),anchorOrtho=this.anchorOrtho(),anchorOrthoLength=this.anchorOrthoLength(),rootScene=this._getRootScene();var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(tickScene){var markWrapped=Object.create(this);markWrapped.index=this.parent.index;return v1f.call(markWrapped,tickScene.vars.tick.rawValue)}}}var pvTicksPanel=new pvc.visual.Panel(this,this.pvPanel,{extensionId:'ticksPanel'}).lock('data',rootScene.childNodes).lock(anchorOpposite,0).lockMark(anchorOrtho,function(tickScene){return scale(tickScene.vars.tick.value)}).lock('strokeStyle',null).lock('fillStyle',null).lock('lineWidth',0).pvMark.zOrder(20);if(this.showTicks){var pvTicks=this.pvTicks=new pvc.visual.Rule(this,pvTicksPanel,{extensionId:'ticks',wrapper:wrapper}).lock('data').override('defaultColor',function(){return pvRule.scene?pvRule.scene[0].strokeStyle:"#666666"}).lock(anchorOpposite,0).lock(anchorOrtho,0).lock(anchorLength,null).optional(anchorOrthoLength,this.tickLength).pvMark;if(this.showMinorTicks){var layoutInfo=this._layoutInfo;var ticks=layoutInfo.ticks;var tickCount=ticks.length;var minorTickOffset=tickCount>1?Math.abs(scale(ticks[1])-scale(ticks[0]))/2:0;this.pvMinorTicks=new pvc.visual.Rule(this,this.pvTicks,{extensionId:'minorTicks',wrapper:wrapper}).lock('data').intercept('visible',function(){var visible=(this.index=rootPanel.width()){return'right'}}return'center'})}else{label.textAlign(anchorOpposite).textBaseline(function(tickScene){var absTop;if(this.index===0){absTop=label.toScreenTransform().transformVPosition(label.top());if(absTop>=rootPanel.height()){return'bottom'}}else if(this.index===tickScene.parent.childNodes.length-1){absTop=label.toScreenTransform().transformVPosition(label.top());if(absTop<=0){return'top'}}return'middle'})}},_onV1Click:function(context,handler){if(this.isDiscrete&&this.useCompositeAxis){handler.call(context.pvMark,context.scene,context.event)}},_onV1DoubleClick:function(context,handler){if(this.isDiscrete&&this.useCompositeAxis){handler.call(context.pvMark,context.scene,context.event)}},_getSelectableMarks:function(){if(this.isDiscrete&&this.isVisible&&this.pvLabel){return[this.pvLabel]}},renderCompositeOrdinalAxis:function(){var myself=this,isTopOrBottom=this.isAnchorTopOrBottom(),axisDirection=isTopOrBottom?'h':'v',diagDepthCutoff=2,vertDepthCutoff=2,font=this.font;var diagMargin=pv.Text.fontHeight(font)/2;var layout=this._pvLayout=this.getLayoutSingleCluster();layout.node.def("fitInfo",null).height(function(tickScene,e,f){var fitInfo=pvc.text.getFitInfo(tickScene.dx,tickScene.dy,tickScene.vars.tick.label,font,diagMargin);if(!fitInfo.h){if(axisDirection==='v'&&fitInfo.v){vertDepthCutoff=Math.min(diagDepthCutoff,tickScene.depth)}else{diagDepthCutoff=Math.min(diagDepthCutoff,tickScene.depth)}}this.fitInfo(fitInfo);return tickScene.dy});layout.node.add(pv.Bar).fillStyle('rgba(127,127,127,.001)').strokeStyle(function(tickScene){if(tickScene.maxDepth===1||!tickScene.maxDepth){return null}return"rgba(127,127,127,0.3)"}).lineWidth(function(tickScene){if(tickScene.maxDepth===1||!tickScene.maxDepth){return 0}return 0.5}).text(function(tickScene){return tickScene.vars.tick.label});var H_CUTOFF_ANG=0.30,V_CUTOFF_ANG=1.27;var align=isTopOrBottom?"center":(this.anchor=="left")?"right":"left";var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(tickScene){return v1f.call(this,tickScene)}}}this.pvLabel=new pvc.visual.Label(this,layout.label,{extensionId:'label',noClick:false,noDoubleClick:false,noSelect:false,noTooltip:false,noHover:false,wrapper:wrapper,tooltipArgs:{isLazy:false,buildTooltip:function(context){return context.scene.vars.tick.label},options:{gravity:this._calcTipsyGravity(),offset:diagMargin*2}}}).pvMark.def('lblDirection','h').textAngle(function(tickScene){if(tickScene.depth>=vertDepthCutoff&&tickScene.depth=diagDepthCutoff){var tan=tickScene.dy/tickScene.dx;var angle=Math.atan(tan);if(angle>V_CUTOFF_ANG){this.lblDirection('v');return-Math.PI/2}if(angle>H_CUTOFF_ANG){this.lblDirection('d');return-angle}}this.lblDirection('h');return 0}).textMargin(1).textAlign(function(tickScene){return(axisDirection!='v'||tickScene.depth>=vertDepthCutoff||tickScene.depth>=diagDepthCutoff)?'center':align}).left(function(tickScene){return(axisDirection!='v'||tickScene.depth>=vertDepthCutoff||tickScene.depth>=diagDepthCutoff)?tickScene.x+tickScene.dx/2:((align=='right')?tickScene.x+tickScene.dx:tickScene.x)}).font(font).textStyle("#666666").text(function(tickScene){var fitInfo=this.fitInfo();var label=tickScene.vars.tick.label;switch(this.lblDirection()){case'h':if(!fitInfo.h){return pvc.text.trimToWidth(tickScene.dx,label,font,'..')}break;case'v':if(!fitInfo.v){return pvc.text.trimToWidth(tickScene.dy,label,font,'..')}break;case'd':if(!fitInfo.d){var diagonalLength=Math.sqrt(tickScene.dy*tickScene.dy+tickScene.dx*tickScene.dx);return pvc.text.trimToWidth(diagonalLength-diagMargin,label,font,'..')}break}return label})},getLayoutSingleCluster:function(){var rootScene=this._getRootScene(),orientation=this.anchor,maxDepth=rootScene.group.treeHeight,depthLength=this._layoutInfo.axisSize;maxDepth++;var baseDisplacement=depthLength/maxDepth,margin=maxDepth>2?((1/12)*depthLength):0;baseDisplacement-=margin;var scaleFactor=maxDepth/(maxDepth-1),orthoLength=pvc.BasePanel.orthogonalLength[orientation];var displacement=(orthoLength=='width')?(orientation==='left'?[-baseDisplacement,0]:[baseDisplacement,0]):(orientation==='top'?[0,-baseDisplacement]:[0,baseDisplacement]);this.pvRule.sign.override('defaultColor',def.fun.constant(null)).override('defaultStrokeWidth',def.fun.constant(0));var panel=this.pvRule.add(pv.Panel)[orthoLength](depthLength).strokeStyle(null).lineWidth(0).add(pv.Panel)[orthoLength](depthLength*scaleFactor).strokeStyle(null).lineWidth(0);panel.transform(pv.Transform.identity.translate(displacement[0],displacement[1]));return panel.add(pv.Layout.Cluster.Fill).nodes(rootScene.nodes()).orient(orientation)},_calcTipsyGravity:function(){switch(this.anchor){case'bottom':return's';case'top':return'n';case'left':return'w';case'right':return'e'}return's'}}); -def.type('pvc.AxisTitlePanel',pvc.TitlePanelAbstract).init(function(chart,parent,axis,options){this.axis=axis;this.base(chart,parent,options);this._extensionPrefix=axis.extensionPrefixes.map(function(prefix){return prefix+'Title'})}).add({_calcLayout:function(layoutInfo){var scale=this.axis.scale;if(!scale||scale.isNull){return new pvc.Size(0,0)}return this.base(layoutInfo)},_createCore:function(layoutInfo){var scale=this.axis.scale;if(!scale||scale.isNull){return}return this.base(layoutInfo)}}); -def.type('pvc.PieChartPanel',pvc.PlotPanel).init(function(chart,parent,plot,options){var labelStyle=plot.option('ValuesLabelStyle');this.base(chart,parent,plot,options);this.explodedOffsetRadius=plot.option('ExplodedSliceRadius');this.explodedSliceIndex=plot.option('ExplodedSliceIndex');this.activeOffsetRadius=plot.option('ActiveSliceRadius');this.labelStyle=labelStyle;if(labelStyle==='linked'){this.linkInsetRadius=plot.option('LinkInsetRadius');this.linkOutsetRadius=plot.option('LinkOutsetRadius');this.linkMargin=plot.option('LinkMargin');this.linkHandleWidth=plot.option('LinkHandleWidth');this.linkLabelSize=plot.option('LinkLabelSize');this.linkLabelSpacingMin=plot.option('LinkLabelSpacingMin')}}).add({pvPie:null,pvPieLabel:null,valueRoleName:'value',_getV1Datum:function(scene){var datum=scene.datum;if(datum){var datumEx=Object.create(datum);datumEx.percent=scene.vars.value.percent;datum=datumEx}return datum},_calcLayout:function(layoutInfo){var clientSize=layoutInfo.clientSize;var clientWidth=clientSize.width;var clientRadius=Math.min(clientWidth,clientSize.height)/2;if(!clientRadius){return new pvc.Size(0,0)}var center=pv.vector(clientSize.width/2,clientSize.height/2);function resolvePercentRadius(radius){return def.between(pvc.PercentValue.resolve(radius,clientRadius),0,clientRadius)}function resolvePercentWidth(width){return def.between(pvc.PercentValue.resolve(width,clientWidth),0,clientWidth)}var labelFont=this._getConstantExtension('label','font');if(!def.string.is(labelFont)){labelFont=this.valuesFont}var maxPieRadius=clientRadius;if(this.valuesVisible&&this.labelStyle==='linked'){var linkInsetRadius=resolvePercentRadius(this.linkInsetRadius);var linkOutsetRadius=resolvePercentRadius(this.linkOutsetRadius);var linkMargin=resolvePercentWidth(this.linkMargin);var linkLabelSize=resolvePercentWidth(this.linkLabelSize);var textMargin=def.number.to(this._getConstantExtension('label','textMargin'),3);var textHeight=pv.Text.fontHeight(labelFont);var linkHandleWidth=this.linkHandleWidth*textHeight;linkMargin+=linkHandleWidth;var linkLabelSpacingMin=this.linkLabelSpacingMin*textHeight;var freeWidthSpace=Math.max(0,clientWidth/2-clientRadius);var spaceH=Math.max(0,linkOutsetRadius+linkMargin+linkLabelSize-freeWidthSpace);var spaceV=linkOutsetRadius+textHeight;var linkAndLabelRadius=Math.max(0,spaceV,spaceH);if(linkAndLabelRadius>=maxPieRadius){this.valuesVisible=false;if(pvc.debug>=2){this._log("Hiding linked labels due to insufficient space.")}}else{maxPieRadius-=linkAndLabelRadius;layoutInfo.link={insetRadius:linkInsetRadius,outsetRadius:linkOutsetRadius,elbowRadius:maxPieRadius+linkOutsetRadius,linkMargin:linkMargin,handleWidth:linkHandleWidth,labelSize:linkLabelSize,maxTextWidth:linkLabelSize-textMargin,labelSpacingMin:linkLabelSpacingMin,textMargin:textMargin,lineHeight:textHeight}}}var explodedOffsetRadius=resolvePercentRadius(this.explodedOffsetRadius);var activeOffsetRadius=0;if(this.chart.options.hoverable){activeOffsetRadius=resolvePercentRadius(this.activeOffsetRadius)}var effectOffsetRadius=explodedOffsetRadius+activeOffsetRadius;var normalPieRadius=maxPieRadius-effectOffsetRadius;if(normalPieRadius<0){return new pvc.Size(0,0)}layoutInfo.center=center;layoutInfo.clientRadius=clientRadius;layoutInfo.normalRadius=normalPieRadius;layoutInfo.explodedOffsetRadius=explodedOffsetRadius;layoutInfo.activeOffsetRadius=activeOffsetRadius;layoutInfo.labelFont=labelFont},_createCore:function(layoutInfo){var myself=this;var chart=this.chart;var options=chart.options;var visibleKeyArgs={visible:true};var rootScene=this._buildScene();var center=layoutInfo.center;var normalRadius=layoutInfo.normalRadius;var wrapper;var extensionIds=['slice'];if(this.compatVersion()<=1){extensionIds.push('');wrapper=function(v1f){return function(pieCatScene){return v1f.call(this,pieCatScene.vars.value.value)}}}this.pvPie=new pvc.visual.PieSlice(this,this.pvPanel,{extensionId:extensionIds,center:center,activeOffsetRadius:layoutInfo.activeOffsetRadius,wrapper:wrapper,tooltipArgs:{options:{useCorners:true,gravity:function(){var isRightPlane=Math.cos(this.midAngle())>=0;var isTopPlane=Math.sin(this.midAngle())>=0;return isRightPlane?(isTopPlane?'nw':'sw'):(isTopPlane?'ne':'se')}}}}).lock('data',rootScene.childNodes).override('angle',function(){return this.scene.vars.value.angle}).override('baseOffsetRadius',function(){var explodeIndex=myself.explodedSliceIndex;if(explodeIndex==null||explodeIndex==this.pvMark.index){return layoutInfo.explodedOffsetRadius}return this.base()}).lock('outerRadius',function(){return chart.animate(0,normalRadius)}).localProperty('innerRadiusEx',pvc.PercentValue.parse).intercept('innerRadius',function(scene){var innerRadius=this.delegateExtension();if(innerRadius==null){var innerRadiusPct=this.pvMark.innerRadiusEx();if(innerRadiusPct!=null){innerRadius=pvc.PercentValue.resolve(innerRadiusPct,this.pvMark.outerRadius())||0}else{innerRadius=0}}return innerRadius>0?chart.animate(0,innerRadius):0}).pvMark;if(this.valuesVisible){if(this.labelStyle==='inside'){this.pvPieLabel=new pvc.visual.Label(this,this.pvPie.anchor(this.valuesAnchor),{extensionId:'label',wrapper:wrapper}).intercept('visible',function(scene){var angle=scene.vars.value.angle;if(angle<0.001){return false}return this.delegateExtension(true)}).pvMark.text(function(scene){return scene.vars.value.sliceLabel}).textMargin(10)}else if(this.labelStyle==='linked'){var linkLayout=layoutInfo.link;rootScene.layoutLinkLabels(layoutInfo);this.pvLinkPanel=this.pvPanel.add(pv.Panel).data(rootScene.childNodes).localProperty('pieSlice').pieSlice(function(scene){return myself.pvPie.scene[this.index]});this.pvLinkLine=new pvc.visual.Line(this,this.pvLinkPanel,{extensionId:'linkLine',freePosition:true,noClick:true,noDoubleClick:true,noSelect:true,noTooltip:true,noHover:true}).lockMark('data',function(scene){var pieSlice=this.parent.pieSlice();var midAngle=pieSlice.startAngle+pieSlice.angle/2;var outerRadius=pieSlice.outerRadius-linkLayout.insetRadius;var x=pieSlice.left+outerRadius*Math.cos(midAngle);var y=pieSlice.top+outerRadius*Math.sin(midAngle);var firstDotScene=scene.childNodes[0];if(!firstDotScene||!firstDotScene._isFirstDynamicScene){firstDotScene=new pvc.visual.PieLinkLineScene(scene,x,y,0);firstDotScene._isFirstDynamicScene=true}else{firstDotScene.x=x;firstDotScene.y=y}return scene.childNodes}).override('defaultColor',function(type){if(type==='stroke'){return'black'}return this.base(type)}).override('defaultStrokeWidth',def.fun.constant(0.5)).pvMark.lock('visible').lock('top',function(dot){return dot.y}).lock('left',function(dot){return dot.x});this.pvPieLabel=new pvc.visual.Label(this,this.pvLinkPanel,{extensionId:'label',noClick:false,noDoubleClick:false,noSelect:false,noHover:false}).lockMark('data',function(scene){return scene.lineScenes}).pvMark.lock('visible').left(function(scene){return scene.vars.link.labelX}).top(function(scene){return scene.vars.link.labelY+((this.index+1)*linkLayout.lineHeight)}).textAlign(function(scene){return scene.vars.link.labelAnchor}).textMargin(linkLayout.textMargin).textBaseline('bottom').text(function(scene){return scene.vars.link.labelLines[this.index]}).fillStyle('red');if(pvc.debug>=20){this.pvPanel.add(pv.Panel).zOrder(-10).left(center.x-layoutInfo.clientRadius).top(center.y-layoutInfo.clientRadius).width(layoutInfo.clientRadius*2).height(layoutInfo.clientRadius*2).strokeStyle('red');this.pvPanel.strokeStyle('green');var linkColors=pv.Colors.category10();this.pvLinkLine.segmented(true).strokeStyle(function(){return linkColors(this.index)})}}this.pvPieLabel.font(layoutInfo.labelFont)}},_getExtensionId:function(){var extensionIds=[{abs:'content'}];if(this.chart.parent){extensionIds.push({abs:'smallContent'})}return extensionIds.concat(this.base())},renderInteractive:function(){this.pvPanel.render()},_getSelectableMarks:function(){var marks=[this.pvPie];if(this.pvPieLabel){marks.push(this.pvPieLabel)}return marks},_buildScene:function(){var rootScene=new pvc.visual.PieRootScene(this);this.sum=rootScene.vars.sumAbs.value;return rootScene}});def.type('pvc.visual.PieRootScene',pvc.visual.Scene).init(function(panel){var chart=panel.chart;var data=chart.visualRoles('category').flatten(chart.data,pvc.data.visibleKeyArgs);var colorVarHelper=new pvc.visual.RoleVarHelper(chart,chart._colorRole);this.base(null,{panel:panel,group:data});var valueRoleName=panel.valueRoleName;var valueDimName=chart.visualRoles(valueRoleName).firstDimensionName();var valueDim=data.dimensions(valueDimName);var options=chart.options;var percentValueFormat=options.percentValueFormat;var rootScene=this;var sumAbs=0;var CategSceneClass=def.type(pvc.visual.PieCategoryScene).init(function(categData,value){this.base(rootScene,{group:categData});this.vars.category=pvc.visual.ValueLabelVar.fromComplex(categData);sumAbs+=Math.abs(value);this.vars.value=new pvc.visual.ValueLabelVar(value,formatValue(value,categData));colorVarHelper.onNewScene(this,true)});panel._extendSceneType('category',CategSceneClass,['sliceLabel','sliceLabelMask']);data.children().each(function(categData){var value=categData.dimensions(valueDimName).sum(pvc.data.visibleKeyArgs);if(value!==0){new CategSceneClass(categData,value)}});this.angleScale=pv.Scale.linear(0,sumAbs).range(0,2*Math.PI).by1(Math.abs);this.vars.sumAbs=new pvc.visual.ValueLabelVar(sumAbs,formatValue(sumAbs));this.childNodes.forEach(function(categScene){completeBuildCategScene.call(categScene)});function formatValue(value,categData){if(categData){var datums=categData._datums;if(datums.length===1){return datums[0].atoms[valueDimName].label}}return valueDim.format(value)}function completeBuildCategScene(){var valueVar=this.vars.value;valueVar.angle=this.parent.angleScale(valueVar.value);var percent=Math.abs(valueVar.value)/sumAbs;valueVar.percent=new pvc.visual.ValueLabelVar(percent,percentValueFormat(percent));valueVar.sliceLabel=this.sliceLabel()}}).add({layoutLinkLabels:function(layoutInfo){var startAngle=-Math.PI/2;var leftScenes=[];var rightScenes=[];this.childNodes.forEach(function(categScene){startAngle=categScene.layoutI(layoutInfo,startAngle);(categScene.vars.link.dir>0?rightScenes:leftScenes).push(categScene)});this._distributeLabels(-1,leftScenes,layoutInfo);this._distributeLabels(+1,rightScenes,layoutInfo)},_distributeLabels:function(dir,scenes,layoutInfo){scenes.sort(function(sceneA,sceneB){return def.compare(sceneA.vars.link.targetY,sceneB.vars.link.targetY)});this._distributeLabelsDownwards(scenes,layoutInfo)&&this._distributeLabelsUpwards(scenes,layoutInfo)&&this._distributeLabelsEvenly(scenes,layoutInfo);scenes.forEach(function(categScene){categScene.layoutII(layoutInfo)})},_distributeLabelsDownwards:function(scenes,layoutInfo){var linkLayout=layoutInfo.link;var labelSpacingMin=linkLayout.labelSpacingMin;var yMax=layoutInfo.clientSize.height;var overlapping=false;for(var i=0,J=scenes.length-1;itargetYMax){overlapping=true;linkVar1.targetY=targetYMax}else{linkVar1.targetY=targetY1}}}return overlapping},_distributeLabelsUpwards:function(scenes,layoutInfo){var linkLayout=layoutInfo.link;var labelSpacingMin=linkLayout.labelSpacingMin;var overlapping=false;for(var i=scenes.length-1;i>0;i--){var linkVar1=scenes[i-1].vars.link;var linkVar0=scenes[i].vars.link;if(i===1&&linkVar1.labelTop()<0){overlapping=true}var labelBottomMax1=linkVar0.labelTop()-labelSpacingMin;if(linkVar1.labelBottom()>labelBottomMax1){var halfLabelHeight1=linkVar1.labelHeight/2;var targetY1=labelBottomMax1-halfLabelHeight1;var targetYMin=halfLabelHeight1;if(targetY11){labelSpacing/=(scenes.length-1)}var y=0;scenes.forEach(function(scene){var linkVar=scene.vars.link;var halfLabelHeight=linkVar.labelHeight/2;y+=halfLabelHeight;linkVar.targetY=y;y+=halfLabelHeight+labelSpacing});return true}});def.type('pvc.visual.PieLinkLabelVar').add({labelTop:function(){return this.targetY-this.labelHeight/2},labelBottom:function(){return this.targetY+this.labelHeight/2}});def.type('pvc.visual.PieCategoryScene',pvc.visual.Scene).add({sliceLabelMask:function(){return this.panel().valuesMask},sliceLabel:function(){return this.format(this.sliceLabelMask())},layoutI:function(layoutInfo,startAngle){var valueVar=this.vars.value;var endAngle=startAngle+valueVar.angle;var midAngle=(startAngle+endAngle)/2;var linkVar=(this.vars.link=new pvc.visual.PieLinkLabelVar());var linkLayout=layoutInfo.link;var labelLines=pvc.text.justify(valueVar.sliceLabel,linkLayout.maxTextWidth,layoutInfo.labelFont);var lineCount=labelLines.length;linkVar.labelLines=labelLines;linkVar.labelHeight=lineCount*linkLayout.lineHeight;this.lineScenes=def.array.create(lineCount,this);var cosMid=Math.cos(midAngle);var sinMid=Math.sin(midAngle);var isAtRight=cosMid>=0;var dir=isAtRight?1:-1;linkVar.labelAnchor=isAtRight?'left':'right';var center=layoutInfo.center;var elbowRadius=linkLayout.elbowRadius;var elbowX=center.x+elbowRadius*cosMid;var elbowY=center.y+elbowRadius*sinMid;var anchorX=center.x+dir*elbowRadius;var targetX=anchorX+dir*linkLayout.linkMargin;new pvc.visual.PieLinkLineScene(this,elbowX,elbowY);new pvc.visual.PieLinkLineScene(this,anchorX,elbowY);linkVar.elbowY=elbowY;linkVar.targetY=elbowY+0;linkVar.targetX=targetX;linkVar.dir=dir;return endAngle},layoutII:function(layoutInfo){var linkVar=this.vars.link;var targetY=linkVar.targetY;var targetX=linkVar.targetX;var handleWidth=layoutInfo.link.handleWidth;if(handleWidth>0){new pvc.visual.PieLinkLineScene(this,targetX-linkVar.dir*handleWidth,targetY)}new pvc.visual.PieLinkLineScene(this,targetX,targetY);linkVar.labelX=targetX;linkVar.labelY=targetY-linkVar.labelHeight/2}});def.type('pvc.visual.PieLinkLineScene',pvc.visual.Scene).init(function(catScene,x,y,index){this.base(catScene,{group:catScene.group,index:index});this.x=x;this.y=y}).add(pv.Vector); -def.type('pvc.PieChart',pvc.BaseChart).add({_animatable:true,pieChartPanel:null,_getColorRoleSpec:function(){return{isRequired:true,defaultSourceRole:'category',defaultDimension:'color*',requireIsDiscrete:true}},_initVisualRoles:function(){this.base();this._addVisualRole('category',{isRequired:true,defaultDimension:'category*',autoCreateDimension:true});this._addVisualRole('value',{isMeasure:true,isRequired:true,isPercent:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:'value'})},_initPlotsCore:function(){new pvc.visual.PiePlot(this)},_preRenderContent:function(contentOptions){this.base();var isV1Compat=this.compatVersion()<=1;if(isV1Compat){var innerGap=pvc.castNumber(this.options.innerGap)||0.95;innerGap=def.between(innerGap,0.1,1);contentOptions.paddings=((1-innerGap)*100/2).toFixed(2)+"%"}else if(contentOptions.paddings==null){contentOptions.paddings=new pvc.PercentValue(0.025)}var piePlot=this.plots.pie;this.pieChartPanel=new pvc.PieChartPanel(this,this.basePanel,piePlot,def.create(contentOptions,{scenes:def.getPath(this.options,'pie.scenes')}))}}); -def.type('pvc.BarAbstractPanel',pvc.CategoricalAbstractPanel).add({pvBar:null,pvBarLabel:null,pvCategoryPanel:null,pvSecondLine:null,pvSecondDot:null,_creating:function(){var groupScene=this.defaultVisibleBulletGroupScene();if(groupScene&&!groupScene.hasRenderer()){var colorAxis=groupScene.colorAxis;var drawLine=colorAxis.option('LegendDrawLine');var drawMarker=!drawLine||colorAxis.option('LegendDrawMarker');if(drawMarker){var keyArgs={drawMarker:true,markerShape:colorAxis.option('LegendShape'),drawRule:drawLine,markerPvProto:new pv.Mark()};this.extend(keyArgs.markerPvProto,'',{constOnly:true});groupScene.renderer(new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs))}}},_createCore:function(){this.base();var me=this,chart=me.chart,plot=me.plot,isStacked=!!me.stacked,isVertical=me.isOrientationVertical(),data=me.visibleData(),seriesData=me.visualRoles.series.flatten(data),rootScene=me._buildScene(data,seriesData),orthoAxis=me.axes.ortho,baseAxis=me.axes.base,orthoScale=orthoAxis.scale,orthoZero=orthoScale(0),sceneOrthoScale=orthoAxis.sceneScale({sceneVarName:'value',nullToZero:false}),sceneBaseScale=baseAxis.sceneScale({sceneVarName:'category'}),barSizeRatio=plot.option('BarSizeRatio'),barSizeMax=plot.option('BarSizeMax'),barStackedMargin=plot.option('BarStackedMargin'),baseRange=baseAxis.scale.range(),bandWidth=baseRange.band,barStepWidth=baseRange.step,barWidth,reverseSeries=isVertical===isStacked;if(isStacked){barWidth=bandWidth}else{var S=seriesData.childCount();barWidth=S>0?(bandWidth*barSizeRatio/S):0}if(barWidth>barSizeMax){barWidth=barSizeMax}me.barWidth=barWidth;me.barStepWidth=barStepWidth;var wrapper;if(me.compatVersion()<=1){wrapper=function(v1f){return function(scene){var markParent=Object.create(this.parent);var mark=Object.create(this);mark.parent=markParent;var serIndex=scene.parent.childIndex();var catIndex=scene.childIndex();if(isStacked){markParent.index=serIndex;mark.index=catIndex}else{markParent.index=catIndex;mark.index=serIndex}return v1f.call(mark,scene.vars.value.rawValue)}}}me.pvBarPanel=new pvc.visual.Panel(me,me.pvPanel,{panelType:pv.Layout.Band,extensionId:'panel'}).lock('layers',rootScene.childNodes).lockMark('values',function(seriesScene){return seriesScene.childNodes}).lockMark('orient',isVertical?'bottom-left':'left-bottom').lockMark('layout',isStacked?'stacked':'grouped').lockMark('verticalMode',me._barVerticalMode()).lockMark('yZero',orthoZero).pvMark.band.x(sceneBaseScale).w(bandWidth).differentialControl(me._barDifferentialControl()).item.order(reverseSeries?"reverse":null).h(function(scene){var y=sceneOrthoScale(scene);return y!=null?chart.animate(0,y-orthoZero):null}).w(barWidth).horizontalRatio(barSizeRatio).verticalMargin(barStackedMargin).end;this.pvBar=new pvc.visual.Bar(me,me.pvBarPanel.item,{extensionId:'',freePosition:true,wrapper:wrapper}).lockDimensions().pvMark.antialias(false);if(plot.option('OverflowMarkersVisible')){this._addOverflowMarkers(wrapper)}if(me.valuesVisible){me.pvBarLabel=new pvc.visual.Label(me,me.pvBar.anchor(me.valuesAnchor||'center'),{extensionId:'label',wrapper:wrapper}).pvMark.visible(function(){var length=this.scene.target[this.index][isVertical?'height':'width'];return length>=4}).font(me.valuesFont).text(function(scene){return scene.format(me.valuesMask)})}},_barVerticalMode:function(){return null},_barDifferentialControl:function(){return null},_getV1Datum:function(scene){var datum=scene.datum;if(datum){var datumEx=Object.create(datum);datumEx.percent=scene.vars.value.percent;datum=datumEx}return datum},_addOverflowMarkers:function(wrapper){var orthoAxis=this.axes.ortho;if(orthoAxis.option('FixedMax')!=null){this.pvOverflowMarker=this._addOverflowMarker(false,orthoAxis.scale,wrapper)}if(orthoAxis.option('FixedMin')!=null){this.pvUnderflowMarker=this._addOverflowMarker(true,orthoAxis.scale,wrapper)}},_addOverflowMarker:function(isMin,orthoScale,wrapper){var isVertical=this.isOrientationVertical(),a_bottom=isVertical?"bottom":"left",a_top=this.anchorOpposite(a_bottom),a_height=this.anchorOrthoLength(a_bottom),a_width=this.anchorLength(a_bottom),paddings=this._layoutInfo.paddings,rOrthoBound=isMin?(orthoScale.min-paddings[a_bottom]):(orthoScale.max+paddings[a_top]),angle;if(!isMin){angle=isVertical?Math.PI:-Math.PI/2}else{angle=isVertical?0:Math.PI/2}return new pvc.visual.Dot(this,this.pvBar.anchor('center'),{noSelect:true,noHover:true,noClick:true,noDoubleClick:true,noTooltip:true,freePosition:true,extensionId:isMin?'underflowMarker':'overflowMarker',wrapper:wrapper}).intercept('visible',function(scene){var visible=this.delegateExtension();if(visible!==undefined&&!visible){return false}var value=scene.vars.value.value;if(value==null){return false}var targetInstance=this.pvMark.scene.target[this.index];var orthoMaxPos=targetInstance[a_bottom]+(value>0?targetInstance[a_height]:0);return isMin?(orthoMaxPosrOrthoBound)}).lock(a_top,null).lock('shapeSize').pvMark.shape("triangle").shapeRadius(function(){return Math.min(Math.sqrt(10),this.scene.target[this.index][a_width]/2)}).shapeAngle(angle).lineWidth(1.5).strokeStyle("red").fillStyle("white")[a_bottom](function(){return rOrthoBound+(isMin?1:-1)*(this.shapeRadius()+2)})},renderInteractive:function(){this.pvPanel.render()},_getSelectableMarks:function(){return[this.pvBar]},_buildScene:function(data,seriesData){var rootScene=new pvc.visual.Scene(null,{panel:this,group:data});var categDatas=data._children;var roles=this.visualRoles;var valueVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.value,{hasPercentSubVar:this.stacked});var colorVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.color);seriesData.children().each(createSeriesScene);return rootScene;function createSeriesScene(seriesData1){var seriesScene=new pvc.visual.Scene(rootScene,{group:seriesData1}),seriesKey=seriesData1.key;seriesScene.vars.series=pvc.visual.ValueLabelVar.fromComplex(seriesData1);colorVarHelper.onNewScene(seriesScene,false);categDatas.forEach(function(categData1){var group=data._childrenByKey[categData1.key]._childrenByKey[seriesKey],scene=new pvc.visual.Scene(seriesScene,{group:group});var categVar=scene.vars.category=pvc.visual.ValueLabelVar.fromComplex(categData1);categVar.group=categData1;valueVarHelper.onNewScene(scene,true);colorVarHelper.onNewScene(scene,true)})}}}); -def.type('pvc.BarAbstract',pvc.CategoricalAbstract).init(function(options){this.base(options);var parent=this.parent;if(parent){this._valueRole=parent._valueRole}}).add({_initVisualRoles:function(){this.base();this._addVisualRole('value',{isMeasure:true,isRequired:true,isPercent:this.options.stacked,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:'value'});this._valueRole=this.visualRoles('value')},_getCategoryRoleSpec:function(){var catRoleSpec=this.base();catRoleSpec.requireIsDiscrete=true;return catRoleSpec},_initData:function(){this.base.apply(this,arguments);var data=this.data;this._valueDim=data.dimensions(this._valueRole.firstDimensionName())}}); -def.type('pvc.BarPanel',pvc.BarAbstractPanel).add({}); -def.type('pvc.BarChart',pvc.BarAbstract).add({_animatable:true,_allowV1SecondAxis:true,_initPlotsCore:function(){var options=this.options;var barPlot=new pvc.visual.BarPlot(this);var trend=barPlot.option('Trend');if(options.plot2){var plot2Plot=new pvc.visual.PointPlot(this,{name:'plot2',fixed:{DataPart:'1'},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:true}});if(!trend){trend=plot2Plot.option('Trend')}}if(trend){new pvc.visual.PointPlot(this,{name:'trend',fixed:{DataPart:'trend',TrendType:'none',ColorRole:'series',NullInterpolatioMode:'none'},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:false}})}},_hasDataPartRole:function(){return true},_createPlotPanels:function(parentPanel,baseOptions){var plots=this.plots;var barPlot=plots.bar;var barPanel=new pvc.BarPanel(this,parentPanel,barPlot,Object.create(baseOptions));this.barChartPanel=barPanel;var plot2Plot=plots.plot2;if(plot2Plot){if(pvc.debug>=3){this._log("Creating Point panel.")}var pointPanel=new pvc.PointPanel(this,parentPanel,plot2Plot,Object.create(baseOptions));barPanel.pvSecondLine=pointPanel.pvLine;barPanel.pvSecondDot=pointPanel.pvDot;pointPanel._applyV1BarSecondExtensions=true}var trendPlot=plots.trend;if(trendPlot){if(pvc.debug>=3){this._log("Creating Trends Point panel.")}new pvc.PointPanel(this,parentPanel,trendPlot,Object.create(baseOptions))}}}); -def.type('pvc.NormalizedBarPanel',pvc.BarAbstractPanel).add({_barVerticalMode:function(){return'expand'}}); -def.type('pvc.NormalizedBarChart',pvc.BarAbstract).add({_processOptionsCore:function(options){options.stacked=true;this.base(options)},_getContinuousVisibleExtentConstrained:function(axis,min,max){if(axis.type==='ortho'){return{min:0,max:100,minLocked:true,maxLocked:true}}return this.base(axis,min,max)},_initPlotsCore:function(hasMultiRole){new pvc.visual.NormalizedBarPlot(this)},_createPlotPanels:function(parentPanel,baseOptions){var barPlot=this.plots.bar;this.barChartPanel=new pvc.NormalizedBarPanel(this,parentPanel,barPlot,Object.create(baseOptions))}}); -def.type('pvc.visual.legend.WaterfallBulletGroupScene',pvc.visual.Scene).init(function(rootScene,keyArgs){this.base(rootScene,keyArgs);this.extensionPrefix=def.get(keyArgs,'extensionPrefix')||'';var item=this.createItem({value:null,rawValue:null,label:def.get(keyArgs,'label')});item.color=def.get(keyArgs,'color')}).add({hasRenderer:function(){return this._renderer},renderer:function(renderer){if(renderer!=null){this._renderer=renderer}return this._renderer},itemSceneType:function(){var ItemType=this._itemSceneType;if(!ItemType){ItemType=def.type(pvc.visual.legend.BulletItemScene);this.panel()._extendSceneType('item',ItemType,['isOn','isClickable','click']);this._itemSceneType=ItemType}return ItemType},createItem:function(keyArgs){var ItemType=this.itemSceneType();return new ItemType(this,keyArgs)}}); -def.type('pvc.WaterfallPanel',pvc.BarAbstractPanel).add({pvWaterfallLine:null,ruleData:null,_barDifferentialControl:function(){var isFalling=this.chart._isFalling;return function(scene){if(isFalling&&!this.index){return 1}var group=scene.vars.category.group;if(group._isFlattenGroup&&!group._isDegenerateFlattenGroup){return-2}return isFalling?-1:1}},_creating:function(){var rootScene=this._getLegendBulletRootScene();if(rootScene){var waterfallGroupScene=rootScene.firstChild;if(waterfallGroupScene&&!waterfallGroupScene.hasRenderer()){var keyArgs={drawRule:true,drawMarker:false,noSelect:true,noHover:true,rulePvProto:new pv.Mark()};this.extend(keyArgs.rulePvProto,'line',{constOnly:true});waterfallGroupScene.renderer(new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs))}}},_createCore:function(){this.base();var chart=this.chart,isVertical=this.isOrientationVertical(),anchor=isVertical?"bottom":"left",ao=this.anchorOrtho(anchor),ruleRootScene=this._buildRuleScene(),orthoScale=chart.axes.ortho.scale,orthoPanelMargin=0.04*(orthoScale.range()[1]-orthoScale.range()[0]),orthoZero=orthoScale(0),sceneOrthoScale=chart.axes.ortho.sceneScale({sceneVarName:'value'}),sceneBaseScale=chart.axes.base.sceneScale({sceneVarName:'category'}),baseScale=chart.axes.base.scale,barWidth2=this.barWidth/2,barWidth=this.barWidth,barStepWidth=this.barStepWidth,isFalling=chart._isFalling,waterColor=chart._waterColor;if(this.plot.option('AreasVisible')){var panelColors=pv.Colors.category10();var waterGroupRootScene=this._buildWaterGroupScene();this.pvWaterfallGroupPanel=new pvc.visual.Panel(this,this.pvPanel,{extensionId:'group'}).lock('data',waterGroupRootScene.childNodes).pvMark.zOrder(-1).fillStyle(function(){return panelColors(0).alpha(0.15)})[ao](function(scene){var categVar=scene.vars.category;return baseScale(categVar.leftValue)-barStepWidth/2})[this.anchorLength(anchor)](function(scene){var categVar=scene.vars.category,length=Math.abs(baseScale(categVar.rightValue)-baseScale(categVar.leftValue));return length+barStepWidth})[anchor](function(scene){return orthoScale(scene.vars.value.bottomValue)-orthoPanelMargin/2})[this.anchorOrthoLength(anchor)](function(scene){return orthoScale(scene.vars.value.heightValue)+orthoPanelMargin})}this.pvBar.sign.override('baseColor',function(type){var color=this.base(type);if(type==='fill'){if(!this.scene.vars.category.group._isFlattenGroup){return pv.color(color).alpha(0.5)}}return color});this.pvWaterfallLine=new pvc.visual.Rule(this,this.pvPanel,{extensionId:'line',noTooltip:false,noHover:false,noSelect:false,noClick:false,noDoubleClick:false}).lock('data',ruleRootScene.childNodes).optional('visible',function(){return(isFalling&&!!this.scene.previousSibling)||(!isFalling&&!!this.scene.nextSibling)}).optional(anchor,function(){return orthoZero+chart.animate(0,sceneOrthoScale(this.scene)-orthoZero)}).optional(this.anchorLength(anchor),barStepWidth+barWidth).optional(ao,isFalling?function(){return sceneBaseScale(this.scene)-barStepWidth-barWidth2}:function(){return sceneBaseScale(this.scene)-barWidth2}).override('defaultColor',function(){return waterColor}).pvMark.antialias(true).lineCap('butt');if(this.plot.option('TotalValuesVisible')){this.pvWaterfallLabel=new pvc.visual.Label(this,this.pvWaterfallLine,{extensionId:'lineLabel'}).intercept('visible',function(scene){if(scene.vars.category.group._isFlattenGroup){return false}return isFalling||!!scene.nextSibling}).pvMark[anchor](function(scene){return orthoZero+chart.animate(0,sceneOrthoScale(scene)-orthoZero)})[this.anchorOrtho(anchor)](sceneBaseScale).textAlign(isVertical?'center':'left').textBaseline(function(categScene){if(!isVertical){return'middle'}var direction=categScene.vars.direction;if(direction==null){return'bottom'}var isRising=!isFalling;return(isRising===(direction==='up')?'bottom':'top')}).textStyle(pv.Color.names.darkgray.darker(2)).textMargin(5).text(function(scene){return scene.vars.value.label})}},_buildRuleScene:function(){var rootScene=new pvc.visual.Scene(null,{panel:this,group:this.visibleData()});var prevValue;if(this.chart._ruleInfos){this.chart._ruleInfos.forEach(createCategScene,this)}return rootScene;function createCategScene(ruleInfo){var categData1=ruleInfo.group;var categScene=new pvc.visual.Scene(rootScene,{group:categData1});var categVar=categScene.vars.category=pvc.visual.ValueLabelVar.fromComplex(categData1);categVar.group=categData1;var value=ruleInfo.offset;categScene.vars.value=new pvc.visual.ValueLabelVar(value,this.chart._valueDim.format(value));categScene.vars.direction=(prevValue==null||prevValue===value)?null:(prevValueresult.max){result.max=offset}if(offset=0){return dmin>=0?dmin:dmax}return 0});var orthoZero=orthoScale(orthoNullValue);var sceneBaseScale=this.axes.base.sceneScale({sceneVarName:'category'});def.scope(function(){var serRole=chart._serRole;return(serRole&&serRole.grouping)?serRole.flatten(data).children():def.query([null])}).each(function(seriesData1){var seriesScene=new pvc.visual.Scene(rootScene,{group:seriesData1||data});seriesScene.vars.series=pvc.visual.ValueLabelVar.fromComplex(seriesData1);colorVarHelper.onNewScene(seriesScene,false);categDatas.forEach(function(categData,categIndex){var group=categData;if(seriesData1){group=group._childrenByKey[seriesData1.key]}var value=group?group.dimensions(valueDim.name).sum(visibleKeyArgs):null;var serCatScene=new pvc.visual.Scene(seriesScene,{group:group});serCatScene.dataIndex=categIndex;serCatScene.vars.category=pvc.visual.ValueLabelVar.fromComplex(categData);var valueVar=new pvc.visual.ValueLabelVar(value,valueDim.format(value),value);valueVar.accValue=value!=null?value:orthoNullValue;serCatScene.vars.value=valueVar;colorVarHelper.onNewScene(serCatScene,true);var isInterpolated=false;if(group){var firstDatum=group._datums[0];if(firstDatum&&firstDatum.isInterpolated){isInterpolated=true}}serCatScene.isInterpolated=isInterpolated;serCatScene.isNull=value==null;serCatScene.isIntermediate=false},this)},this);var reversedSeriesScenes=rootScene.children().reverse().array();var belowSeriesScenes2;reversedSeriesScenes.forEach(completeSeriesScenes,this);reversedSeriesScenes.forEach(trimNullSeriesScenes,this);return rootScene;function completeSeriesScenes(seriesScene){var seriesScenes2=[],seriesScenes=seriesScene.childNodes,fromScene,notNullCount=0,firstAloneScene=null;for(var c=0,toChildIndex=0,categCount=seriesScenes.length;c=3){this._log("Creating second Point panel.")}new pvc.PointPanel(this,parentPanel,plot2Plot,Object.create(baseOptions))}var trendPlot=plots.trend;if(trendPlot){if(pvc.debug>=3){this._log("Creating Trends Point panel.")}new pvc.PointPanel(this,parentPanel,trendPlot,Object.create(baseOptions))}},defaults:{tooltipOffset:10}});def.type('pvc.DotChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{DotsVisible:true}})}});def.type('pvc.LineChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{LinesVisible:true}})}});def.type('pvc.AreaChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{AreasVisible:true}})}});pvc.mStackedLineChart=def.type('pvc.StackedLineChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{LinesVisible:true,Stacked:true}})}});def.type('pvc.StackedDotChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{DotsVisible:true,Stacked:true}})}});pvc.mStackedAreaChart=def.type('pvc.StackedAreaChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{AreasVisible:true,Stacked:true},defaults:{LinesVisible:true}})}}); -def.type('pvc.HeatGridPanel',pvc.CategoricalAbstractPanel).init(function(chart,parent,plot,options){this.base(chart,parent,plot,options);this.axes.size=chart._getAxis('size',plot.option('SizeAxis')-1);var roles=this.visualRoles;var sizeRoleName=plot.option('SizeRole');roles.size=chart.visualRoles(sizeRoleName);var valueDimName;if(roles.color.isBound()){valueDimName=roles.color.firstDimensionName()}else if(roles.size.isBound()){valueDimName=roles.size.firstDimensionName()}this._valueDimName=valueDimName;this.useShapes=plot.option('UseShapes');this.shape=plot.option('Shape');this.nullShape=plot.option('NullShape')}).add({pvHeatGrid:null,pvHeatGridLabel:null,defaultBorder:1,nullBorder:2,selectedBorder:2,_createCore:function(){this.base();var chart=this.chart;var a_bottom=this.isOrientationVertical()?"bottom":"left";var xScale=this.axes.x.scale;var yScale=this.axes.y.scale;var w=(xScale.max-xScale.min)/xScale.domain().length;var h=(yScale.max-yScale.min)/yScale.domain().length;if(a_bottom!=="bottom"){var tmp=w;w=h;h=tmp}this._cellWidth=w;this._cellHeight=h;var keyArgs={visible:true},rowRootData=chart.data.flattenBy(chart._serRole,keyArgs),data=this.visibleData(),rootScene=this._buildScene(data,rowRootData),hasColor=rootScene.hasColorRole,hasSize=rootScene.hasSizeRole;var getFillColor;var colorAxis=this.axes.color;var colorNull=colorAxis.option('Missing');if(hasColor){var fillColorScaleByColKey=colorAxis.scalesByCateg;if(fillColorScaleByColKey){getFillColor=function(leafScene){var colorValue=leafScene.vars.color.value;if(colorValue==null){return colorNull}var colAbsKey=leafScene.group.parent.absKey;return fillColorScaleByColKey[colAbsKey](colorValue)}}else{var colorScale=colorAxis.scale;getFillColor=function(leafScene){return colorScale(leafScene.vars.color.value)}}}else{getFillColor=def.fun.constant(colorNull)}var a_left=pvc.BasePanel.relativeAnchor[a_bottom];var a_width=pvc.BasePanel.parallelLength[a_bottom];var a_height=pvc.BasePanel.orthogonalLength[a_bottom];var pvRowPanel=new pvc.visual.Panel(this,this.pvPanel).pvMark.data(rootScene.childNodes)[a_bottom](function(){return this.index*h})[a_height](h);var wrapper;if(this.compatVersion()<=1){var colorValuesBySerAndCat=def.query(rootScene.childNodes).object({name:function(serScene){return''+serScene.vars.series.value},value:function(serScene){return def.query(serScene.childNodes).object({name:function(leafScene){return''+leafScene.vars.category.value},value:function(leafScene){var colorVar=leafScene.vars.color;return colorVar?(''+colorVar.value):null}})}});wrapper=function(v1f){return function(leafScene){var colorValuesByCat=colorValuesBySerAndCat[leafScene.vars.series.value];var cat=leafScene.vars.category.rawValue;var wrapperParent=Object.create(this.parent);var wrapper=Object.create(this);wrapper.parent=wrapperParent;var catIndex=leafScene.childIndex();var serIndex=leafScene.parent.childIndex();wrapperParent.index=catIndex;wrapper.index=serIndex;return v1f.call(wrapper,colorValuesByCat,cat)}}}var extensionIds=['panel'];if(this.compatVersion()<=1){extensionIds.push('')}keyArgs={extensionId:extensionIds,wrapper:wrapper};if(!this.useShapes){keyArgs.noSelect=keyArgs.noHover=keyArgs.noClick=keyArgs.noDoubleClick=keyArgs.freeColor=false;keyArgs.noTooltip=!!wrapper}var pvHeatGrid=this.pvHeatGrid=new pvc.visual.Panel(this,pvRowPanel,keyArgs).lock('data',function(serScene){return serScene.childNodes}).pvMark.localProperty('colorValue').lock('colorValue',function(leafScene){return leafScene.vars.color.value}).localProperty('sizeValue').lock('sizeValue',function(leafScene){return leafScene.vars.size.value}).lock(a_left,function(){return this.index*w}).lock(a_width,w).antialias(false);if(this.useShapes){this.shapes=this.createHeatMap(w,h,getFillColor,wrapper,hasColor,hasSize)}else{this.shapes=pvHeatGrid.sign.override('defaultColor',function(type){if(type==='stroke'){return null}return getFillColor.call(this.pvMark,this.scene)}).override('interactiveColor',function(color,type){var scene=this.scene;if(scene.isActive){return color.alpha(0.6)}if(scene.anySelected()&&!scene.isSelected()){return this.dimColor(color,type)}return this.base(color,type)}).override('dimColor',function(color){return pvc.toGrayScale(color,0.6)}).pvMark.lineWidth(1.5)}if(this.valuesVisible&&this._valueDimName){var valueDimName=this._valueDimName;this.pvHeatGridLabel=new pvc.visual.Label(this,this.pvHeatGrid.anchor("center"),{extensionId:'label',wrapper:wrapper}).pvMark.font(this.valuesFont).text(function(leafScene){return leafScene.atoms[valueDimName].label})}},_calcDotAreaRange:function(w,h){var maxRadius=Math.min(w,h)/2;if(this.shape==='diamond'){maxRadius/=Math.SQRT2}maxRadius-=2;var maxArea=maxRadius*maxRadius,minArea=12,areaSpan=maxArea-minArea;if(areaSpan<=1){maxArea=Math.max(maxArea,2);minArea=1;areaSpan=maxArea-minArea;if(pvc.debug>=2){this._log("Using rescue mode dot area calculation due to insufficient space.")}}return{min:minArea,max:maxArea,span:areaSpan}},createHeatMap:function(w,h,getFillColor,wrapper,hasColor,hasSize){var me=this,chart=me.chart,nullShapeType=me.nullShape,shapeType=me.shape;var areaRange=me._calcDotAreaRange(w,h);var maxArea=areaRange.max;var sizeScale;if(hasSize){sizeScale=me.axes.size.setScaleRange(areaRange).scale}var notNullSelectedBorder=(me.selectedBorder==null||(+me.selectedBorder)===0)?me.defaultBorder:me.selectedBorder;var nullSelectedBorder=(me.selectedBorder==null||(+me.selectedBorder)===0)?me.nullBorder:me.selectedBorder;var nullDeselectedBorder=me.defaultBorder>0?me.defaultBorder:me.nullBorder;var getShapeSize,getShapeType;if(!hasSize){getShapeType=def.fun.constant(shapeType);getShapeSize=function(){return(hasColor&&!nullShapeType&&this.parent.colorValue()==null)?0:maxArea}}else{getShapeType=function(){return this.parent.sizeValue()!=null?shapeType:nullShapeType};getShapeSize=function(){var sizeValue=this.parent.sizeValue();return(sizeValue==null&&!nullShapeType)?0:sizeScale(sizeValue)}}var keyArgs={extensionId:'dot',freePosition:true,activeSeriesAware:false,noHover:false,wrapper:wrapper};var options=chart.options;if(wrapper&&chart._tooltipEnabled){var customTooltip=options.customTooltip;if(!customTooltip){customTooltip=function(s,c,d){if(d!=null&&d[0]!==undefined){return d.join(', ')}return d}}keyArgs.tooltipArgs={buildTooltip:options.isMultiValued?function(context){var group=context.scene.group;var s=pvc.data.Complex.values(group,chart._serRole.grouping.dimensionNames());var c=pvc.data.Complex.values(group,chart._catRole.grouping.dimensionNames());var d=[];if(hasSize){d[options.sizeValIdx||0]=context.scene.vars.size.value}if(hasColor){d[options.colorValIdx||0]=context.scene.vars.color.value}return customTooltip.call(options,s,c,d)}:function(context){var s=context.scene.vars.series.rawValue;var c=context.scene.vars.category.rawValue;var valueVar=context.scene.vars[hasColor?'color':'size'];var d=valueVar?valueVar.value:null;return customTooltip.call(options,s,c,d)}}}return new pvc.visual.Dot(me,me.pvHeatGrid,keyArgs).override('defaultSize',function(){return getShapeSize.call(this.pvMark,this.scene)}).override('interactiveSize',function(size){if(this.scene.isActive){return Math.max(size,5)*1.5}return size}).override('baseColor',function(){return getFillColor.call(this.pvMark.parent,this.scene)}).override('normalColor',function(color,type){if(type==='stroke'){return color.darker()}return this.base(color,type)}).override('interactiveColor',function(color,type){var scene=this.scene;if(type==='stroke'){if(scene.anySelected()&&!scene.isSelected()){return color}return color.darker()}if(scene.isActive){return color.alpha(0.6)}return this.base(color,type)}).override('dimColor',function(color){return pvc.toGrayScale(color,0.6)}).pvMark.shape(getShapeType).lock('shapeAngle').lineWidth(function(leafScene){if(!hasSize||!me._isNullShapeLineOnly()||this.parent.sizeValue()!=null){return leafScene.isSelected()?notNullSelectedBorder:me.defaultBorder}return leafScene.isSelected()?nullSelectedBorder:nullDeselectedBorder})},_isNullShapeLineOnly:function(){return this.nullShape=='cross'},_getSelectableMarks:function(){return[this.shapes]},renderInteractive:function(){this.pvPanel.render()},_buildScene:function(data,seriesRootData){var me=this;var rootScene=new pvc.visual.Scene(null,{panel:me,group:data});var categDatas=data._children;var roles=me.visualRoles;var colorVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.color);var sizeVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.size);rootScene.hasColorRole=colorVarHelper.isBound();rootScene.hasSizeRole=sizeVarHelper.isBound();seriesRootData.children().each(createSeriesScene);return rootScene;function createSeriesScene(serData1){var serScene=new pvc.visual.Scene(rootScene,{group:serData1});serScene.vars.series=pvc.visual.ValueLabelVar.fromComplex(serData1);categDatas.forEach(function(catData1){createSeriesCategoryScene.call(me,serScene,catData1,serData1)})}function createSeriesCategoryScene(serScene,catData1,serData1){var group=data._childrenByKey[catData1.key]._childrenByKey[serData1.key];var serCatScene=new pvc.visual.Scene(serScene,{group:group});serCatScene.vars.category=pvc.visual.ValueLabelVar.fromComplex(catData1);colorVarHelper.onNewScene(serCatScene,true);sizeVarHelper.onNewScene(serCatScene,true)}}}); -def.type('pvc.HeatGridChart',pvc.CategoricalAbstract).add({_allowColorPerCategory:true,_axisCreateIfUnbound:{'color':true},_processOptionsCore:function(options){this.base(options);def.set(options,'orthoAxisOrdinal',true,'legend',false,'panelSizeRatio',1);var colorDimName='value',sizeDimName='value2';if(this.compatVersion()<=1){switch(this.options.colorValIdx){case 0:colorDimName='value';break;case 1:colorDimName='value2';break;default:colorDimName='value'}switch(this.options.sizeValIdx){case 0:sizeDimName='value';break;case 1:sizeDimName='value2';break;default:sizeDimName='value'}}this._colorDimName=colorDimName;this._sizeDimName=sizeDimName},_getCategoryRoleSpec:function(){var catRoleSpec=this.base();catRoleSpec.requireIsDiscrete=true;return catRoleSpec},_getColorRoleSpec:function(){return{isMeasure:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:this._colorDimName}},_initVisualRoles:function(){this.base();this._addVisualRole('size',{isMeasure:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:this._sizeDimName})},_initPlotsCore:function(){new pvc.visual.HeatGridPlot(this)},_collectPlotAxesDataCells:function(plot,dataCellsByAxisTypeThenIndex){this.base(plot,dataCellsByAxisTypeThenIndex);if(plot.type==='heatGrid'&&plot.option('UseShapes')){var sizeRole=this.visualRoles(plot.option('SizeRole'));if(sizeRole.isBound()){var sizeDataCellsByAxisIndex=def.array.lazy(dataCellsByAxisTypeThenIndex,'size');def.array.lazy(sizeDataCellsByAxisIndex,plot.option('SizeAxis')-1).push({plot:plot,role:sizeRole,dataPartValue:plot.option('DataPart')})}}},_setAxesScales:function(hasMultiRole){this.base(hasMultiRole);if(!hasMultiRole||this.parent){var sizeAxis=this.axes.size;if(sizeAxis&&sizeAxis.isBound()){this._createAxisScale(sizeAxis)}}},_createPlotPanels:function(parentPanel,baseOptions){var heatGridPlot=this.plots.heatGrid;this.heatGridChartPanel=new pvc.HeatGridPanel(this,parentPanel,heatGridPlot,Object.create(baseOptions))},defaults:{colorValIdx:0,sizeValIdx:1,measuresIndexes:[2],axisOffset:0,plotFrameVisible:false,colorNormByCategory:true,numSD:2}}); -def.type('pvc.MetricXYAbstract',pvc.CartesianAbstract).init(function(options){this.base(options);var parent=this.parent;if(parent){this._xRole=parent._xRole;this._yRole=parent._yRole}}).add({_processOptionsCore:function(options){this.base(options);options.panelSizeRatio=1},_initVisualRoles:function(){this.base();this._xRole=this._addVisualRole('x',{isMeasure:true,isRequired:true,requireSingleDimension:true,requireIsDiscrete:false,defaultDimension:'x',dimensionDefaults:{valueType:this.options.timeSeries?Date:Number}});this._yRole=this._addVisualRole('y',{isMeasure:true,isRequired:true,requireSingleDimension:true,requireIsDiscrete:false,defaultDimension:'y',dimensionDefaults:{valueType:Number}})},_initData:function(){this.base.apply(this,arguments);this._xDim=this.data.dimensions(this._xRole.firstDimensionName());this._yDim=this.data.dimensions(this._yRole.firstDimensionName())},_generateTrendsDataCellCore:function(newDatums,dataCell,trendInfo){var serRole=this._serRole;var xRole=this._xRole;var yRole=dataCell.role;var trendOptions=dataCell.trend;this._warnSingleContinuousValueRole(yRole);var dataPartDimName=this._dataPartRole.firstDimensionName();var xDimName=xRole.firstDimensionName();var yDimName=yRole.firstDimensionName();var data=this.visibleData(dataCell.dataPartValue);def.scope(function(){return serRole.isBound()?data.children():def.query([data])}).each(genSeriesTrend,this);function genSeriesTrend(serData){var funX=function(datum){return datum.atoms[xDimName].value};var funY=function(datum){return datum.atoms[yDimName].value};var datums=serData.datums().sort(null,funX).array();var options=def.create(trendOptions,{rows:def.query(datums),x:funX,y:funY});var trendModel=trendInfo.model(options);if(trendModel){var dataPartAtom=data.owner.dimensions(dataPartDimName).intern(this.root._firstTrendAtomProto);datums.forEach(function(datum,index){var trendX=funX(datum);if(trendX){var trendY=trendModel.sample(trendX,funY(datum),index);if(trendY!=null){var atoms=def.set(Object.create(serData.atoms),xDimName,trendX,yDimName,trendY,dataPartDimName,dataPartAtom);newDatums.push(def.set(new pvc.data.Datum(data.owner,atoms),'isVirtual',true,'isTrend',true,'trendType',trendInfo.type))}}})}}}}); -def.type('pvc.data.MetricPointChartTranslationOper').add({_meaLayoutRoles:['x','y','color','size'],configureType:function(){var itemTypes=this._itemTypes;var V=itemTypes.length;var freeMeaIndexes=[];var freeDisIndexes=[];def.range(0,V).each(function(j){if(!this._userUsedIndexes[j]){if(itemTypes[j]===1){freeMeaIndexes.push(j)}else{freeDisIndexes.push(j)}}},this);var N;var autoDimNames=[];var F=freeMeaIndexes.length;if(F>0){var R=this._meaLayoutRoles.length;var i=0;while(i0){freeMeaIndexes.length=N;this.defReader({names:autoDimNames,indexes:freeMeaIndexes})}}F=freeDisIndexes.length;if(F>0){autoDimNames.length=0;this._getUnboundRoleDefaultDimNames('series',F,autoDimNames);N=autoDimNames.length;if(N>0){freeDisIndexes.length=N;this.defReader({names:autoDimNames,indexes:freeDisIndexes})}}}}); -def.type('pvc.MetricPointPanel',pvc.CartesianAbstractPanel).init(function(chart,parent,plot,options){this.base(chart,parent,plot,options);this.axes.size=chart._getAxis('size',(plot.option('SizeAxis')||0)-1);var sizeRoleName=plot.option('SizeRole');this.visualRoles.size=chart.visualRoles(sizeRoleName);this.linesVisible=plot.option('LinesVisible');this.dotsVisible=plot.option('DotsVisible');if(!this.linesVisible&&!this.dotsVisible){this.linesVisible=true;plot.option.specify({'LinesVisible':true})}this.dotShape=plot.option('Shape');if(!this.offsetPaddings){this.offsetPaddings=new pvc.Sides(0.01)}}).add({pvLine:null,pvDot:null,pvLabel:null,pvScatterPanel:null,dotShape:"circle",sizeAxisRatio:1/5,sizeAxisRatioTo:'minWidthHeight',autoPaddingByDotSize:true,_v1DimRoleName:{'category':'x','value':'y'},_creating:function(){var groupScene=this.defaultVisibleBulletGroupScene();if(groupScene&&!groupScene.hasRenderer()){var colorAxis=groupScene.colorAxis;var drawMarker=def.nullyTo(colorAxis.option('LegendDrawMarker',true),this.dotsVisible);var drawRule=def.nullyTo(colorAxis.option('LegendDrawLine',true),this.linesVisible);if(drawMarker||drawRule){var keyArgs={};if((keyArgs.drawMarker=drawMarker)){keyArgs.markerShape=colorAxis.option('LegendShape',true)||'circle';keyArgs.markerPvProto=new pv.Dot().lineWidth(1.5,pvc.extensionTag).shapeSize(12,pvc.extensionTag);this.extend(keyArgs.markerPvProto,'dot',{constOnly:true})}if((keyArgs.drawRule=drawRule)){keyArgs.rulePvProto=new pv.Line().lineWidth(1.5,pvc.extensionTag);this.extend(keyArgs.rulePvProto,'line',{constOnly:true})}groupScene.renderer(new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs))}}},_getRootScene:function(){var me=this;var rootScene=me._rootScene;if(!rootScene){var roles=me.visualRoles;var hasColorRole=roles.color.isBound()&&!me.axes.color.scale.isNull;var hasSizeRole=roles.size.isBound()&&!me.axes.size.scale.isNull;me._rootScene=rootScene=me._buildScene(hasColorRole,hasSizeRole)}return rootScene},_calcLayout:function(layoutInfo){var rootScene=this._getRootScene();if(rootScene.hasSizeRole){var areaRange=this._calcDotAreaRange(layoutInfo);this.sizeScale=this.axes.size.setScaleRange(areaRange).scale}this._calcAxesPadding(layoutInfo,rootScene)},_getDotDiameterRefLength:function(layoutInfo){var clientSize=layoutInfo.clientSize;var paddings=layoutInfo.paddings;switch(this.sizeAxisRatioTo){case'minWidthHeight':return Math.min(clientSize.width+paddings.width,clientSize.height+paddings.height);case'width':return clientSize.width+paddings.width;case'height':return clientSize.height+paddings.height}if(pvc.debug>=2){this._log(def.format("Invalid option 'sizeAxisRatioTo' value. Assuming 'minWidthHeight'.",[this.sizeAxisRatioTo]))}this.sizeRatioTo='minWidthHeight';return this._getDotDiameterRefLength(layoutInfo)},_calcDotRadiusRange:function(layoutInfo){var refLength=this._getDotDiameterRefLength(layoutInfo);var max=(this.sizeAxisRatio/2)*refLength;var min=Math.sqrt(12);return{min:min,max:max}},_calcDotAreaRange:function(layoutInfo){var radiusRange=this._calcDotRadiusRange(layoutInfo);if(this.dotShape==='diamond'){radiusRange.max/=Math.SQRT2;radiusRange.min/=Math.SQRT2}var maxArea=radiusRange.max*radiusRange.max,minArea=radiusRange.min*radiusRange.min,areaSpan=maxArea-minArea;if(areaSpan<=1){maxArea=Math.max(maxArea,2);minArea=1;areaSpan=maxArea-minArea;radiusRange={min:Math.sqrt(minArea),max:Math.sqrt(maxArea)};if(pvc.debug>=3){this._log("Using rescue mode dot area calculation due to insufficient space.")}}return{min:minArea,max:maxArea,span:areaSpan}},_calcAxesPadding:function(layoutInfo,rootScene){var requestPaddings;if(!this.autoPaddingByDotSize){requestPaddings=this._calcRequestPaddings(layoutInfo)}else{var axes=this.axes;var clientSize=layoutInfo.clientSize;var paddings=layoutInfo.paddings;requestPaddings={};axes.x.setScaleRange(clientSize.width);axes.y.setScaleRange(clientSize.height);var sceneXScale=axes.base.sceneScale({sceneVarName:'x'});var sceneYScale=axes.ortho.sceneScale({sceneVarName:'y'});var xLength=axes.base.scale.max;var yLength=axes.ortho.scale.max;var hasSizeRole=rootScene.hasSizeRole;var sizeScale=this.sizeScale;if(!hasSizeRole){var defaultSize=def.number.as(this._getExtension('dot','shapeRadius'),0);if(defaultSize<=0){defaultSize=def.number.as(this._getExtension('dot','shapeSize'),0);if(defaultSize<=0){defaultSize=12}}else{defaultSize=defaultSize*defaultSize}sizeScale=def.fun.constant(defaultSize)}requestPaddings={};var op;if(this.offsetPaddings){op={};pvc.Sides.names.forEach(function(side){var len_a=pvc.BasePanel.orthogonalLength[side];op[side]=(this.offsetPaddings[side]||0)*(clientSize[len_a]+paddings[len_a])},this)}var setSide=function(side,padding){if(op){padding+=(op[side]||0)}if(padding<0){padding=0}var value=requestPaddings[side];if(value==null||padding>value){requestPaddings[side]=padding}};var processScene=function(scene){var x=sceneXScale(scene);var y=sceneYScale(scene);var r=Math.sqrt(sizeScale(hasSizeRole?scene.vars.size.value:0));setSide('left',r-x);setSide('bottom',r-y);setSide('right',x+r-xLength);setSide('top',y+r-yLength)};rootScene.children().selectMany(function(seriesScene){return seriesScene.childNodes}).each(processScene)}layoutInfo.requestPaddings=requestPaddings},_createCore:function(){this.base();var myself=this;var chart=this.chart;var rootScene=this._getRootScene();this._finalizeScene(rootScene);this.pvPanel.zOrder(1);this.pvScatterPanel=new pvc.visual.Panel(this,this.pvPanel,{extensionId:'panel'}).lock('data',rootScene.childNodes).pvMark;var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(dotScene){var d={category:dotScene.vars.x.rawValue,value:dotScene.vars.y.rawValue};var pseudo=Object.create(this);pseudo.index=dotScene.dataIndex;return v1f.call(pseudo,d)}}}var isLineNoSelect=chart._canSelectWithFocusWindow();var line=new pvc.visual.Line(this,this.pvScatterPanel,{extensionId:'line',wrapper:wrapper,noTooltip:false,noHover:true,noSelect:isLineNoSelect,showsSelection:!isLineNoSelect}).lock('data',function(seriesScene){return seriesScene.childNodes}).lock('visible',this.linesVisible).override('x',function(){return this.scene.basePosition}).override('y',function(){return this.scene.orthoPosition});this.pvLine=line.pvMark;var dot=new pvc.visual.Dot(this,this.pvLine,{extensionId:'dot',wrapper:wrapper,activeSeriesAware:this.linesVisible}).intercept('visible',function(){return!this.scene.isIntermediate&&this.delegateExtension(true)}).lock('shape',this.dotShape).override('x',function(){return this.scene.basePosition}).override('y',function(){return this.scene.orthoPosition}).override('color',function(type){if(!myself.dotsVisible){var visible=this.scene.isActive||this.scene.isSingle;if(!visible){return pvc.invisibleFill}}return this.base(type)});this.pvDot=dot.pvMark;this.pvDot.rubberBandSelectionMode='center';dot.override('defaultColor',function(type){var color=this.base(type);if(color&&type==='stroke'){color=color.darker()}return color}).override('interactiveColor',function(color,type){if(type==='stroke'&&this.scene.isActive){return color}return this.base(color,type)});if(!rootScene.hasSizeRole){dot.override('baseSize',function(){if(!myself.dotsVisible){if(this.scene.isSingle){var lineWidth=Math.max(myself.pvLine.scene[this.pvMark.index].lineWidth,0.2)/2;return lineWidth*lineWidth}}return this.base()})}else{var sizeAxis=myself.axes.size;if(sizeAxis.scaleUsesAbs()){dot.override('strokeColor',function(){return this.scene.vars.size.value<0?"#000000":this.base()}).optional('lineCap','round').optionalMark('strokeDasharray',function(scene){return scene.vars.size.value<0?'dot':null}).optionalMark('lineWidth',function(scene){return scene.vars.size.value<0?1.8:1.5})}var sizeScale=this.sizeScale;dot.override('baseSize',function(){return sizeScale(this.scene.vars.size.value)}).override('interactiveSize',function(size){if(this.scene.isActive){var radius=Math.sqrt(size)*1.1;return radius*radius}return size});this.pvPanel.borderPanel.overflow("hidden")}if(this.valuesVisible){var extensionIds=['label'];if(this.compatVersion()<=1){extensionIds.push('lineLabel')}this.pvLabel=new pvc.visual.Label(this,this.pvDot.anchor(this.valuesAnchor),{extensionId:extensionIds,wrapper:wrapper}).pvMark.font(this.valuesFont).text(function(scene){return def.string.join(",",scene.vars.x.label,scene.vars.y.label)})}},renderInteractive:function(){this.pvScatterPanel.render()},_getSelectableMarks:function(){var marks=[];marks.push(this.pvDot);if(this.linesVisible){marks.push(this.pvLine)}return marks},_finalizeScene:function(rootScene){var axes=this.axes,sceneBaseScale=axes.base.sceneScale({sceneVarName:'x'}),sceneOrthoScale=axes.ortho.sceneScale({sceneVarName:'y'});rootScene.children().selectMany(function(seriesScene){return seriesScene.childNodes}).each(function(leafScene){leafScene.basePosition=sceneBaseScale(leafScene);leafScene.orthoPosition=sceneOrthoScale(leafScene)});return rootScene},_buildScene:function(hasColorRole,hasSizeRole){var data=this.visibleData();var rootScene=new pvc.visual.Scene(null,{panel:this,group:data});rootScene.hasColorRole=hasColorRole;rootScene.hasSizeRole=hasSizeRole;var roles=this.visualRoles;var colorVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.color,{forceUnbound:!hasColorRole});var sizeVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.size,{forceUnbound:!hasSizeRole});var xDim=data.owner.dimensions(roles.x.firstDimensionName());var yDim=data.owner.dimensions(roles.y.firstDimensionName());data.children().each(createSeriesScene,this);rootScene.children().each(completeSeriesScenes,this);return rootScene;function createSeriesScene(seriesGroup){var seriesScene=new pvc.visual.Scene(rootScene,{group:seriesGroup});seriesScene.vars.series=pvc.visual.ValueLabelVar.fromComplex(seriesGroup);colorVarHelper.onNewScene(seriesScene,false);seriesGroup.datums().each(function(datum,dataIndex){var xAtom=datum.atoms[xDim.name];if(xAtom.value==null){return}var yAtom=datum.atoms[yDim.name];if(yAtom.value==null){return}var scene=new pvc.visual.Scene(seriesScene,{datum:datum});scene.dataIndex=dataIndex;scene.vars.x=Object.create(xAtom);scene.vars.y=Object.create(yAtom);sizeVarHelper.onNewScene(scene,true);colorVarHelper.onNewScene(scene,true);scene.isIntermediate=false})}function completeSeriesScenes(seriesScene){var seriesScenes=seriesScene.childNodes,fromScene;for(var c=0,toChildIndex=0,pointCount=seriesScenes.length;c4){translation.defReader({names:'range',indexes:pv.range(4,size)})}break}}return translation},_initPlotsCore:function(hasMultiRole){new pvc.visual.BulletPlot(this)},_preRenderContent:function(contentOptions){var bulletPlot=this.plots.bullet;this.bulletChartPanel=new pvc.BulletChartPanel(this,this.basePanel,bulletPlot,def.create(contentOptions,{tooltipEnabled:this._tooltipEnabled}))},defaults:{compatVersion:1,orientation:'horizontal',bulletSize:30,bulletSpacing:50,bulletMargin:100,bulletTitle:"Title",bulletSubtitle:"",bulletTitlePosition:"left",tooltipFormat:function(s,c,v){return this.chart.options.valueFormat(v)},crosstabMode:false,seriesInRows:false}});def.type('pvc.BulletChartPanel',pvc.PlotPanel).add({pvBullets:null,pvBullet:null,data:null,onSelectionChange:null,_createCore:function(layoutInfo){var chart=this.chart,options=chart.options,data=this.buildData();var anchor=options.orientation=="horizontal"?"left":"bottom";var size,angle,align,titleLeftOffset,titleTopOffset,ruleAnchor,leftPos,topPos,titleSpace;if(options.orientation=="horizontal"){size=layoutInfo.clientSize.width-this.chart.options.bulletMargin-20;angle=0;switch(options.bulletTitlePosition){case'top':leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;align='left';titleTopOffset=-12;titleSpace=parseInt(options.titleSize/2,10);break;case'bottom':leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;align='left';titleTopOffset=options.bulletSize+32;titleSpace=0;break;case'right':leftPos=5;titleLeftOffset=size+5;align='left';titleTopOffset=parseInt(options.bulletSize/2,10);titleSpace=0;break;case'left':default:leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;titleTopOffset=parseInt(options.bulletSize/2,10);align='right';titleSpace=0}ruleAnchor="bottom";topPos=function(){return(this.index*(options.bulletSize+options.bulletSpacing))+titleSpace}}else{size=layoutInfo.clientSize.height-this.chart.options.bulletMargin-20;switch(options.bulletTitlePosition){case'top':leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;align='left';titleTopOffset=-20;angle=0;topPos=undefined;break;case'bottom':leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;align='left';titleTopOffset=size+20;angle=0;topPos=20;break;case'right':leftPos=5;titleLeftOffset=this.chart.options.bulletSize+40;align='left';titleTopOffset=size;angle=-Math.PI/2;topPos=undefined;break;case'left':default:leftPos=this.chart.options.bulletMargin;titleLeftOffset=-12;titleTopOffset=this.height-this.chart.options.bulletMargin-20;align='left';angle=-Math.PI/2;topPos=undefined}ruleAnchor="right";leftPos=function(){return options.bulletMargin+this.index*(options.bulletSize+options.bulletSpacing)}}this.pvBullets=this.pvPanel.add(pv.Panel).data(data)[pvc.BasePanel.orthogonalLength[anchor]](size)[pvc.BasePanel.parallelLength[anchor]](this.chart.options.bulletSize).margin(20).left(leftPos).top(topPos);this.pvBullet=this.pvBullets.add(pv.Layout.Bullet).orient(anchor).ranges(function(d){return d.ranges}).measures(function(d){return d.measures}).markers(function(d){return d.markers});if(options.clickable&&this.clickAction){var me=this;this.pvBullet.cursor("pointer").event("click",function(d){var s=d.title;var c=d.subtitle;var ev=pv.event;return me.clickAction(s,c,d.measures,ev)})}this.pvBulletRange=this.pvBullet.range.add(pv.Bar);this.pvBulletMeasure=this.pvBullet.measure.add(pv.Bar).text(function(v,d){return d.formattedMeasures[this.index]});this.pvBulletMarker=this.pvBullet.marker.add(pv.Dot).shape("square").fillStyle("white").text(function(v,d){return d.formattedMarkers[this.index]});if(this.tooltipEnabled){var myself=this;this.pvBulletMeasure.localProperty('tooltip').tooltip(function(v,d){var s=d.title;var c=d.subtitle;return chart.options.tooltipFormat.call(myself,s,c,v)});this.pvBulletMarker.localProperty('tooltip').tooltip(function(v,d){var s=d.title;var c=d.subtitle;return chart.options.tooltipFormat.call(myself,s,c,v)});this.pvBulletMeasure.event("mouseover",pv.Behavior.tipsy(this.chart._tooltipOptions));this.pvBulletMarker.event("mouseover",pv.Behavior.tipsy(this.chart._tooltipOptions))}this.pvBulletRule=this.pvBullet.tick.add(pv.Rule);this.pvBulletRuleLabel=this.pvBulletRule.anchor(ruleAnchor).add(pv.Label).text(this.pvBullet.x.tickFormat);this.pvBulletTitle=this.pvBullet.anchor(anchor).add(pv.Label).font("bold 12px sans-serif").textAngle(angle).left(-10).textAlign(align).textBaseline("bottom").left(titleLeftOffset).top(titleTopOffset).text(function(d){return d.formattedTitle});this.pvBulletSubtitle=this.pvBullet.anchor(anchor).add(pv.Label).textStyle("#666").textAngle(angle).textAlign(align).textBaseline("top").left(titleLeftOffset).top(titleTopOffset).text(function(d){return d.formattedSubtitle});var doubleClickAction=(typeof(options.axisDoubleClickAction)=='function')?function(d,e){options.axisDoubleClickAction(d,e)}:null;if(options.clickable&&doubleClickAction){this.pvBulletTitle.cursor("pointer").events('all').event("dblclick",function(d){doubleClickAction(d,arguments[arguments.length-1])});this.pvBulletSubtitle.cursor("pointer").events('all').event("dblclick",function(d){doubleClickAction(d,arguments[arguments.length-1])})}},applyExtensions:function(){this.base();this.extend(this.pvBullets,"bulletsPanel");this.extend(this.pvBullet,"bulletPanel");this.extend(this.pvBulletRange,"bulletRange");this.extend(this.pvBulletMeasure,"bulletMeasure");this.extend(this.pvBulletMarker,"bulletMarker");this.extend(this.pvBulletRule,"bulletRule");this.extend(this.pvBulletRuleLabel,"bulletRuleLabel");this.extend(this.pvBulletTitle,"bulletTitle");this.extend(this.pvBulletSubtitle,"bulletSubtitle")},_getExtensionId:function(){return[{abs:'content'}].concat(this.base())},buildData:function(){var data,chart=this.chart,options=chart.options,titleRole=chart.visualRoles('title'),titleGrouping=titleRole.grouping,subTitleRole=chart.visualRoles('subTitle'),subTitleGrouping=subTitleRole.grouping,valueRole=chart.visualRoles('value'),valueGrouping=valueRole.grouping,markerRole=chart.visualRoles('marker'),markerGrouping=markerRole.grouping,rangeRole=chart.visualRoles('range'),rangeGrouping=rangeRole.grouping;var defaultData={title:options.bulletTitle,formattedTitle:options.bulletTitle,subtitle:options.bulletSubtitle,formattedSubtitle:options.bulletSubtitle,ranges:def.array.to(options.bulletRanges)||[],measures:def.array.to(options.bulletMeasures)||[],markers:def.array.to(options.bulletMarkers)||[]};def.set(defaultData,'formattedRanges',defaultData.ranges.map(String),'formattedMeasures',defaultData.measures.map(String),'formattedMarkers',defaultData.markers.map(String));if(!valueGrouping&&!titleGrouping&&!markerGrouping&&!subTitleGrouping&&!rangeGrouping){data=[defaultData]}else{data=chart.data.datums().select(function(datum){var d=Object.create(defaultData),view;if(valueGrouping){view=valueGrouping.view(datum);d.measures=view.values();d.formattedMeasures=view.labels()}if(titleGrouping){view=titleGrouping.view(datum);d.title=view.value;d.formattedTitle=view.label}if(subTitleGrouping){view=subTitleGrouping.view(datum);d.subtitle=view.value;d.formattedSubtitle=view.label}if(markerGrouping){view=markerGrouping.view(datum);d.markers=view.values();d.formattedMarkers=view.labels()}if(rangeGrouping){view=rangeGrouping.view(datum);d.ranges=view.values();d.formattedRanges=view.labels()}return d},this).array()}return data}}); -def.type('pvc.ParallelCoordinates',pvc.BaseChart).init(function(options){options=options||{};options.dimensions=options.dimensions||{};if(!options.dimensions.value){options.dimensions.value={valueType:null}}this.base(options)}).add({parCoordPanel:null,_preRenderContent:function(contentOptions){this.parCoordPanel=new pvc.ParCoordPanel(this,this.basePanel,def.create(contentOptions,{topRuleOffset:this.options.topRuleOffset,botRuleOffset:this.options.botRuleOffset,leftRuleOffset:this.options.leftRuleOffset,rightRuleOffset:this.options.rightRuleOffset,sortCategorical:this.options.sortCategorical,mapAllDimensions:this.options.mapAllDimensions,numDigits:this.options.numDigits}))},defaults:def.create(pvc.BaseChart.prototype.defaults,{compatVersion:1,topRuleOffset:30,botRuleOffset:30,leftRuleOffset:60,rightRuleOffset:60,sortCategorical:true,mapAllDimensions:true,numDigits:0})});def.type('pvc.ParCoordPanel',pvc.BasePanel).add({anchor:'fill',pvParCoord:null,dimensions:null,dimensionDescr:null,data:null,retrieveData:function(){var data=this.chart.data;var numDigit=this.chart.options.numDigits;this.dimensions=data.getVisibleCategories();var values=data.getValues();var dataRowIndex=data.getVisibleSeriesIndexes();var pCoordIndex=data.getVisibleCategoriesIndexes();var pCoordKeys=data.getCategories();var pCoordMapping=this.chart.options.mapAllDimensions?pCoordIndex.map(function(d){return isNaN(values[d][0])?{categorical:true,len:0,map:[]}:{categorical:false,len:0,map:[],displayValue:[]}}):pCoordIndex.map(function(d){return isNaN(values[d][0])?{categorical:true,len:0,map:[]}:null});var coordMapUpdate=function(i,val){var cMap=pCoordMapping[i];var k=null;if(!cMap.categorical){var keyVal=val.toFixed(numDigit);k=cMap.map[keyVal];if(k==null){k=cMap.len;cMap.len++;cMap.map[keyVal]=k;cMap.displayValue[keyVal]=val}}else{k=cMap.map[val];if(k==null){k=cMap.len;cMap.len++;cMap.map[val]=k}}return k};for(var d in pCoordMapping){if(pCoordMapping.hasOwnProperty(d)&&pCoordMapping[d]&&pCoordMapping[d].categorical){pCoordMapping[d].displayValue=pCoordMapping[d].map}}var i,item,k;if(this.chart.options.sortCategorical||this.chart.options.mapAllDimensions){for(i=0;i1)?elements[1]:"";return item2});for(i=0;itheMax){theMax2=theMax;theMax=v}}}else{theMin=theMax=theMin2=theMax2=values[index][0];for(k=1;ktheMax){theMax2=theMax;theMax=v}}}var theStep=((theMax-theMax2)+(theMin2-theMin))/2;item.min=theMin;item.max=theMax;item.step=theStep;item.categorical=false;if(pCoordMapping[index]){item.map=pCoordMapping[index].map;item.mapLength=pCoordMapping[index].len;item.categorical=pCoordMapping[index].categorical;if(!item.categorical){item.orgValue=[];var theMap=pCoordMapping[index].map;for(var key in theMap){if(theMap.hasOwnProperty(key)){item.orgValue[theMap[key]]=0.0+key}}}}}var genKeyVal=function(keys,vals){var record={};for(var i=0;i=filter[t].min)&&(val<=filter[t].max)})}:function(d){return dims.every(function(t){return(d[t]>=filter[t].min)&&(d[t]<=filter[t].max)})};var auxData=null;this.pvParCoord=this.pvPanel.add(pv.Panel).data(myself.data).visible(selectVisible).add(pv.Line).data(dims).left(function(t,d){return x(t)}).bottom(function(t,d){var res=y[t](d[t]);return res}).strokeStyle("#ddd").lineWidth(1).antialias(false);var rule=this.pvPanel.add(pv.Rule).data(dims).left(x).top(topRuleOffs).bottom(botRuleOffs);rule.anchor("top").add(pv.Label).top(labelTopOffs).font("bold 10px sans-serif").text(function(d){return dimDescr[d].name});var labels=[];var labelXoffs=6,labelYoffs=3;for(var d in dimDescr){if(dimDescr.hasOwnProperty(d)){var dim=dimDescr[d];if(dim.categorical){var xVal=x(dim.id)+labelXoffs;for(var l in dim.map){if(dim.map.hasOwnProperty(l)){labels[labels.length]={x:xVal,y:y[dim.id](dim.map[l])+labelYoffs,label:l}}}}}}var dimLabels=this.pvPanel.add(pv.Panel).data(labels).add(pv.Label).left(function(d){return d.x}).bottom(function(d){return d.y}).text(function(d){return d.label}).textAlign("left");var change=this.pvPanel.add(pv.Panel);var line=change.add(pv.Panel).data(myself.data).visible(selectVisible).add(pv.Line).data(dims).left(function(t,d){return x(t)}).bottom(function(t,d){return y[t](d[t])}).strokeStyle(function(t,d){var dd=dimDescr[active];var val=(dd.orgValue&&!dd.categorical)?dd.orgValue[d[active]]:d[active];return colors[active](val)}).lineWidth(1);function update(d){var t=d.dim;filter[t].min=Math.max(y[t].domain()[0],y[t].invert(height-d.y-d.dy));filter[t].max=Math.min(y[t].domain()[1],y[t].invert(height-d.y));active=t;change.render();return false}function selectAll(d){if(d.dy<3){var t=d.dim;filter[t].min=Math.max(y[t].domain()[0],y[t].invert(0));filter[t].max=Math.min(y[t].domain()[1],y[t].invert(height));d.y=botRuleOffs;d.dy=ruleHeight;active=t;change.render()}return false}var handle=change.add(pv.Panel).data(dims.map(function(dim){return{y:botRuleOffs,dy:ruleHeight,dim:dim}})).left(function(t){return x(t.dim)-30}).width(60).fillStyle("rgba(0,0,0,.001)").cursor("crosshair").event("mousedown",pv.Behavior.select()).event("select",update).event("selectend",selectAll).add(pv.Bar).left(25).top(function(d){return d.y}).width(10).height(function(d){return d.dy}).fillStyle(function(t){return(t.dim==active)?colors[t.dim]((filter[t.dim].max+filter[t.dim].min)/2):"hsla(0,0,50%,.5)"}).strokeStyle("white").cursor("move").event("mousedown",pv.Behavior.drag()).event("dragstart",update).event("drag",update);handle.anchor("bottom").add(pv.Label).textBaseline("top").text(function(d){return(dimDescr[d.dim].categorical)?"":filter[d.dim].min.toFixed(numDigits)+dimDescr[d.dim].unit});handle.anchor("top").add(pv.Label).textBaseline("bottom").text(function(d){return(dimDescr[d.dim].categorical)?"":filter[d.dim].max.toFixed(numDigits)+dimDescr[d.dim].unit});this.extend(this.pvParCoord,"parCoord");this.extend(this.pvPanel,"chart")}}); -def.type('pvc.DataTree',pvc.BaseChart).init(function(options){options=options||{};options.dimensionGroups=options.dimensionGroups||{};if(!options.dimensionGroups.value){options.dimensionGroups.value={valueType:null}}this.base(options)}).add({structEngine:null,structMetadata:null,structDataset:null,DataTreePanel:null,_getColorRoleSpec:function(){return{isRequired:true,defaultSourceRole:'category',requireIsDiscrete:true}},setStructData:function(data){this.structDataset=data.resultset;if(!this.structDataset.length){this._log("Warning: Structure-dataset is empty")}this.structMetadata=data.metadata;if(!this.structMetadata.length){this._log("Warning: Structure-Metadata is empty")}},_preRenderContent:function(contentOptions){var structEngine=this.structEngine;var structType=structEngine?structEngine.type:new pvc.data.ComplexType();structType.addDimension('value',{});var translOptions={seriesInRows:true,crosstabMode:true};var translation=new pvc.data.CrosstabTranslationOper(structType,this.structDataset,this.structMetadata,translOptions);translation.configureType();if(!structEngine){structEngine=this.structEngine=new pvc.data.Data({type:structType})}structEngine.load(translation.execute(structEngine));if(pvc.debug>=3){this._log(this.structEngine.getInfo())}this.dataTreePanel=new pvc.DataTreePanel(this,this.basePanel,def.create(contentOptions,{topRuleOffset:this.options.topRuleOffset,botRuleOffset:this.options.botRuleOffset,leftRuleOffset:this.options.leftRuleOffset,rightRuleOffset:this.options.rightRuleOffset,boxplotColor:this.options.boxplotColor,valueFontsize:this.options.valueFontsize,headerFontsize:this.options.headerFontsize,border:this.options.border,perpConnector:this.options.perpConnector,numDigits:this.options.numDigits,minVerticalSpace:this.options.minVerticalSpace,connectorSpace:this.options.connectorSpace,minAspectRatio:this.options.minAspectRatio}))},defaults:{compatVersion:1,topRuleOffset:30,botRuleOffset:30,leftRuleOffset:60,rightRuleOffset:60,boxplotColor:"grey",headerFontsize:16,valueFontsize:20,border:2,perpConnector:false,numDigits:0,connectorSpace:0.15,minVerticalSpace:0.05,minAspectRatio:2.0}});def.type('pvc.DataTreePanel',pvc.PlotPanel).add({pvDataTree:null,treeElements:null,structMap:null,structArr:null,hRules:null,vRules:null,rules:null,generatePerpConnectors:function(leftLength){this.hRules=[];this.vRules=[];this.rules=[];for(var e in this.structMap){var elem=this.structMap[e];if(elem.children!=null){var min=+10000,max=-10000;var theLeft=elem.left+elem.width;this.hRules.push({"left":theLeft,"width":leftLength,"bottom":elem.bottom+elem.height/2});theLeft+=leftLength;for(var i in elem.children){var child=this.structMap[elem.children[i]];var theBottom=child.bottom+child.height/2;if(theBottom>max){max=theBottom}if(theBottommin){this.vRules.push({"left":theLeft,"bottom":min,"height":max-min})}}}},generateLineSegment:function(x1,y1,x2,y2){var line=[];line.push({"x":x1,"y":y1});line.push({"x":x2,"y":y2});this.rules.push(line)},generateConnectors:function(leftLength){this.hRules=[];this.vRules=[];if(this.chart.options.perpConnector){this.generatePerpConnectors(leftLength);return}this.rules=[];for(var e in this.structMap){var elem=this.structMap[e];if(elem.children!=null){var theCenter,child,i;var min=+10000,max=-10000;for(i in elem.children){child=this.structMap[elem.children[i]];theCenter=child.bottom+child.height/2;if(theCenter>max){max=theCenter}if(theCenter4);var e;for(e in this.treeElements){this.treeElements[e]=$.trim(this.treeElements[e])}var bounds=[];bounds.getElement=function(label){if(bounds[label]==null){bounds[label]={"min":+10000,"max":-10000}}return bounds[label]};bounds.addValue=function(label,value){var bnd=bounds.getElement(label);if(valuebnd.max){bnd.max=value}return bnd};var col,colnr,elem,row;for(e in this.treeElements){elem=this.treeElements[e];col=elem[0];colnr=col.charCodeAt(0);row=parseInt(elem.slice(1),10);bounds.addValue("__cols",colnr);bounds.addValue(col,row)}var bnds=bounds.getElement("__cols");var gridWidth=this.innerWidth/(bnds.max-bnds.min+1);var connectorWidth=options.connectorSpace*gridWidth;var cellWidth=gridWidth-connectorWidth;var maxCellHeight=cellWidth/options.minAspectRatio;var colBase=bnds.min;delete bounds.__cols;for(e in bounds){bnds=bounds[e];if(typeof bnds=="function"){continue}var numRows=bnds.max-bnds.min+1;bnds.gridHeight=this.innerHeight/numRows;bnds.cellHeight=bnds.gridHeight*(1.0-options.minVerticalSpace);if(bnds.cellHeight>maxCellHeight){bnds.cellHeight=maxCellHeight}bnds.relBottom=(bnds.gridHeight-bnds.cellHeight)/2;bnds.numRows=numRows}var whitespaceQuote=new RegExp('[\\s\"\']+',"g");this.structMap={};for(e in this.treeElements){var box={};elem=this.treeElements[e];box.box_id=elem;this.structMap[elem]=box;col=elem[0];colnr=col.charCodeAt(0);row=parseInt(elem.slice(1),10);bnds=bounds.getElement(col);box.colIndex=colnr-colBase;box.rowIndex=bnds.numRows-(row-bnds.min)-1;box.left=this.leftOffs+box.colIndex*gridWidth;box.width=cellWidth;if(bottomHeightSpecified){box.bottom=values[4][e];box.height=values[5][e]}else{box.bottom=this.botOffs+box.rowIndex*bnds.gridHeight+bnds.relBottom;box.height=bnds.cellHeight}box.label=values[0][e];box.selector=values[1][e];box.aggregation=values[2][e];var children=(values[3][e]||'').replace(whitespaceQuote," ");box.children=(children===" "||children==="")?null:children.split(" ")}this.generateConnectors((gridWidth-cellWidth)/2);this.structArr=[];for(e in this.structMap){elem=this.structMap[e];this.structArr.push(elem)}},findDataValue:function(key,data){for(var i=0;idat[0]){sp.hScale=pv.Scale.linear(dat[0],dat[4])}else{noBox=true;sp.hScale=pv.Scale.linear(dat[0]-1e-10,dat[0]+1e-10)}sp.hScale.range(elem.left+rlMargin,elem.left+elem.width-rlMargin);var avLabel=""+dat[2];var i;for(i=0;i0)&&(typeof window[selPar]!="undefined")){selPar=window[selPar];this.addDataPoint(selPar)}}},_createCore:function(){var myself=this;var options=this.chart.options;options.smValueFontsize=Math.round(0.6*options.valueFontsize);options.smValueFont=""+options.smValueFontsize+"px sans-serif";options.valueFont=""+options.valueFontsize+"px sans-serif";var topRuleOffs=options.topRuleOffset,botRuleOffs=options.botRuleOffset,leftRuleOffs=options.leftRuleOffset;this.innerWidth=this.width-leftRuleOffs-options.rightRuleOffset;this.innerHeight=this.height-topRuleOffs-botRuleOffs;this.botOffs=botRuleOffs;this.leftOffs=leftRuleOffs;this.retrieveStructure();this.retrieveData();var topMargin=options.headerFontsize+3;var rules=this.rules;var i;for(i=0;i=3){this._log("Creating Point panel.")}var pointPanel=new pvc.PointPanel(this,parentPanel,plot2Plot,Object.create(baseOptions));pointPanel._v1DimRoleName.value=plot2Plot.option('OrthoRole')}},defaults:{crosstabMode:false}}).addStatic({measureRolesNames:['median','lowerQuartil','upperQuartil','minimum','maximum']}); diff --git a/pacotes/ccc2/ccc2sage.php b/pacotes/ccc2/ccc2sage.php deleted file mode 100755 index a64e5ab..0000000 --- a/pacotes/ccc2/ccc2sage.php +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/pacotes/ccc2/cdf/jquery.js b/pacotes/ccc2/cdf/jquery.js deleted file mode 100755 index 7c24308..0000000 --- a/pacotes/ccc2/cdf/jquery.js +++ /dev/null @@ -1,154 +0,0 @@ -/*! - * jQuery JavaScript Library v1.4.2 - * http://jquery.com/ - * - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Sat Feb 13 22:33:48 2010 -0500 - */ -(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
"; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/pacotes/ccc2/compactajs.php b/pacotes/ccc2/compactajs.php deleted file mode 100755 index e9bb690..0000000 --- a/pacotes/ccc2/compactajs.php +++ /dev/null @@ -1,221 +0,0 @@ -"; - -$originais = array( -"pvc/pvc.js", -"pvc/pvc.text.js", -"pvc/pvc.color.js", -"pvc/pvc.trends.js", -"pvc/pvc.options.js", -"pvc/data/_data.js", -"pvc/data/meta/DimensionType.js", -"pvc/data/meta/ComplexType.js", -"pvc/data/meta/ComplexTypeProject.js", -"pvc/data/translation/TranslationOper.js", -"pvc/data/translation/MatrixTranslationOper.js", -"pvc/data/translation/CrosstabTranslationOper.js", -"pvc/data/translation/RelationalTranslationOper.js", -"pvc/data/Atom.js", -"pvc/data/Complex.js", -"pvc/data/ComplexView.js", -"pvc/data/Datum.js", -"pvc/data/Dimension.js", -"pvc/data/Data.js", -"pvc/data/Data.selected.js", -"pvc/data/GroupingSpec.js", -"pvc/data/DataOper.js", -"pvc/data/GroupingOper.js", -"pvc/data/LinearInterpolationOper.js", -"pvc/data/LinearInterpolationOperSeriesState.js", -"pvc/data/ZeroInterpolationOper.js", -"pvc/data/ZeroInterpolationOperSeriesState.js", -"pvc/data/Data.operations.js", -"pvc/data/Data.compat.js", -"pvc/visual/Role.js", -"pvc/visual/Scene.js", -"pvc/visual/Var.js", -"pvc/visual/sign/BasicSign.js", -"pvc/visual/sign/Sign.js", -"pvc/visual/sign/Panel.js", -"pvc/visual/sign/Label.js", -"pvc/visual/sign/Dot.js", -"pvc/visual/sign/Line.js", -"pvc/visual/sign/Area.js", -"pvc/visual/sign/Bar.js", -"pvc/visual/sign/PieSlice.js", -"pvc/visual/sign/Rule.js", -"pvc/visual/Context.js", -"pvc/visual/OptionsBase.js", -"pvc/visual/Axis.js", -"pvc/visual/CartesianAxis.js", -"pvc/visual/CartesianAxisRootScene.js", -"pvc/visual/CartesianAxisTickScene.js", -"pvc/visual/CartesianFocusWindow.js", -"pvc/visual/ColorAxis.js", -"pvc/visual/SizeAxis.js", -"pvc/visual/Legend.js", -"pvc/visual/legend/BulletRootScene.js", -"pvc/visual/legend/BulletGroupScene.js", -"pvc/visual/legend/BulletItemScene.js", -"pvc/visual/legend/BulletItemSceneSelection.js", -"pvc/visual/legend/BulletItemSceneVisibility.js", -"pvc/visual/legend/BulletItemRenderer.js", -"pvc/visual/legend/BulletItemDefaultRenderer.js", -"pvc/visual/plot/Plot.js", -"pvc/visual/plot/CartesianPlot.js", -"pvc/visual/plot/CategoricalPlot.js", -"pvc/visual/plot/BarPlotAbstract.js", -"pvc/visual/plot/BarPlot.js", -"pvc/visual/plot/NormalizedBarPlot.js", -"pvc/visual/plot/WaterfallPlot.js", -"pvc/visual/plot/PointPlot.js", -"pvc/visual/plot/MetricXYPlot.js", -"pvc/visual/plot/MetricPointPlot.js", -"pvc/visual/plot/PiePlot.js", -"pvc/visual/plot/HeatGridPlot.js", -"pvc/visual/plot/BoxPlot.js", -"pvc/visual/plot/BulletPlot.js", -"pvc/pvcAbstract.js", -"pvc/pvcBaseChart.js", -"pvc/pvcBaseChart.visualRoles.js", -"pvc/pvcBaseChart.data.js", -"pvc/pvcBaseChart.plots.js", -"pvc/pvcBaseChart.axes.js", -"pvc/pvcBaseChart.panels.js", -"pvc/pvcBaseChart.selection.js", -"pvc/pvcBaseChart.extension.js", -"pvc/pvcBasePanel.js", -"pvc/pvcPlotPanel.js", -"pvc/pvcMultiChartPanel.js", -"pvc/pvcTitlePanelAbstract.js", -"pvc/pvcTitlePanel.js", -"pvc/pvcLegendPanel.js", -"pvc/pvcCartesianAbstract.js", -"pvc/pvcGridDockingPanel.js", -"pvc/pvcCartesianGridDockingPanel.js", -"pvc/pvcCartesianAbstractPanel.js", -"pvc/pvcPlotBgPanel.js", -"pvc/pvcCategoricalAbstract.js", -"pvc/pvcCategoricalAbstractPanel.js", -"pvc/pvcAxisPanel.js", -"pvc/pvcAxisTitlePanel.js", -"pvc/pvcPiePanel.js", -"pvc/pvcPieChart.js", -"pvc/pvcBarAbstractPanel.js", -"pvc/pvcBarAbstract.js", -"pvc/pvcBarPanel.js", -"pvc/pvcBarChart.js", -"pvc/pvcNormalizedBarPanel.js", -"pvc/pvcNormalizedBarChart.js", -"pvc/visual/legend/WaterfallBulletGroupScene.js", -"pvc/pvcWaterfallPanel.js", -"pvc/pvcWaterfallChart.js", -"pvc/pvcPointPanel.js", -"pvc/pvcPoint.js", -"pvc/pvcHeatGridPanel.js", -"pvc/pvcHeatGridChart.js", -"pvc/pvcMetricXYAbstract.js", -"pvc/data/translation/MetricPointChartTranslationOper.js", -"pvc/pvcMetricPointPanel.js", -"pvc/pvcMetricPoint.js", -"pvc/pvcBulletChart.js", -"pvc/pvcParallelCoordinates.js", -"pvc/pvcDataTree.js", -"pvc/data/translation/BoxplotChartTranslationOper.js", -"pvc/pvcBoxplotPanel.js", -"pvc/pvcBoxplotChart.js" -); -$jsfiles = array(); -foreach($originais as $o){ - packer($o,"compacto/".basename($o),"Normal"); - $jsfiles[] = "compacto/".basename($o); -} -echo "

junta tudo
"; - -$buffer = ""; -salvatudojs($jsfiles,$buffer,"ccc2sage.js","js"); - -function inicia($arquivo) -{ - $abre = fopen($arquivo, "r"); - while (!feof($abre)) - { - $buffer = fgets($abre); - $maparray[] = $buffer."kkkk"; - } - fclose($abre); - $c = compress(implode("",$maparray)); - $c = str_replace("kkkk","\n",$c); - $c = str_replace("kkk","",$c); - $c = str_replace(";\n",";",$c); - $c = str_replace("{\n","{",$c); - $c = str_replace("\n}","}",$c); - $c = str_replace(")\n",")",$c); - $c = str_replace(" \n","",$c); - $c = str_replace("\n}","}\n",$c); - return $c; -} -function compress($code) -{ // Remove multiline comment -$mlcomment = '/\/\*(?!-)[\x00-\xff]*?\*\//'; -$code = preg_replace($mlcomment,"",$code); - -// Remove single line comment -$slcomment = '/[^:]\/\/.*/'; -$code = preg_replace($slcomment,"",$code); - -// Remove extra spaces -$extra_space = '/\s+/'; -$code = preg_replace($extra_space," ",$code); - -// Remove spaces that can be removed -$removable_space = '/\s?([\{\};\=\(\)\\\/\+\*-])\s?/'; -$code = preg_replace('/\s?([\{\};\=\(\)\/\+\*-])\s?/',"\\1",$code); -return $code; -} -function packer($src,$out,$tipo="None") -{ - if(file_exists($out)) - {unlink($out);} - require_once '../packer/class.JavaScriptPacker.php'; - $script = file_get_contents($src); - $script = str_replace("if(typeof(console)","//if(typeof(console)",$script); - $t1 = microtime(true); - $packer = new JavaScriptPacker($script, 0, true, false); - $packed = $packer->pack(); - $t2 = microtime(true); - $time = sprintf('%.4f', ($t2 - $t1) ); - echo 'script ', $src, ' packed in ' , $out, ', in ', $time, ' s.', "\n"; - file_put_contents($out, $packed); - chmod($out,0777); -} -function salvatudojs($jsfiles,$buffer,$final,$tipo) -{ - //junta todos os js em um unico - if(file_exists($final)) - {unlink($final);} - foreach ($jsfiles as $f) - { - echo $f; - $linhas = file($f); - foreach($linhas as $linha){ - $linha = trim(preg_replace('#[\r\n]#', '', $linha)); - if($linha != "") - {$buffer .= $linha."\n";} - } - } - $abre = fopen($final, "wt"); - $escreve = fwrite ($abre,$buffer); - $fecha = fclose ($abre); - chmod($final,0777); -} -?> diff --git a/pacotes/ccc2/compacto/Area.js b/pacotes/ccc2/compacto/Area.js deleted file mode 100755 index 0391d3a..0000000 --- a/pacotes/ccc2/compacto/Area.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.Area',pvc.visual.Sign).init(function(panel,protoMark,keyArgs){var pvMark=protoMark.add(pv.Area);if(!keyArgs){keyArgs={}}keyArgs.freeColor=true;this.base(panel,pvMark,keyArgs);var antialias=def.get(keyArgs,'antialias',true);this.lock('segmented','smart').lock('antialias',antialias);if(!def.get(keyArgs,'freePosition',false)){var basePosProp=panel.isOrientationVertical()?"left":"bottom",orthoPosProp=panel.anchorOrtho(basePosProp),orthoLenProp=panel.anchorOrthoLength(orthoPosProp);this._lockDynamic(basePosProp,'x')._lockDynamic(orthoPosProp,'y')._lockDynamic(orthoLenProp,'dy')}this._bindProperty('fillStyle','fillColor','color');this.lock('strokeStyle',null).lock('lineWidth',0)}).add({_addInteractive:function(keyArgs){keyArgs=def.setDefaults(keyArgs,'noTooltip',true);this.base(keyArgs)},x:function(){return 0},y:function(){return 0},dy:function(){return 0},interactiveColor:function(color,type){if(type==='fill'&&this.showsSelection()&&this.scene.anySelected()&&!this.scene.isSelected()){return this.dimColor(color,type)}return this.base(color,type)}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Atom.js b/pacotes/ccc2/compacto/Atom.js deleted file mode 100755 index c4f3a1f..0000000 --- a/pacotes/ccc2/compacto/Atom.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.Atom').init(function(dimension,value,label,rawValue,key){this.dimension=dimension;this.id=(value==null?-def.nextId():def.nextId());this.value=value;this.label=label;if(rawValue!==undefined){this.rawValue=rawValue}this.key=key}).add({isVirtual:false,rawValue:undefined,toString:function(){var label=this.label;if(label!=null){return label}label=this.value;return label!=null?(""+label):""}});function atom_idComparer(a,b){return a.id-b.id}function atom_idComparerReverse(a,b){return b.id-a.id} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Axis.js b/pacotes/ccc2/compacto/Axis.js deleted file mode 100755 index e9a3c7d..0000000 --- a/pacotes/ccc2/compacto/Axis.js +++ /dev/null @@ -1 +0,0 @@ -var axis_optionsDef;def.scope(function(){def.type('pvc.visual.Axis',pvc.visual.OptionsBase).init(function(chart,type,index,keyArgs){this.base(chart,type,index,keyArgs);chart._addAxis(this)}).add({isVisible:true,scaleTreatsNullAs:function(){return'null'},scaleNullRangeValue:function(){return null},scaleUsesAbs:function(){return false},bind:function(dataCells){dataCells||def.fail.argumentRequired('dataCells');!this.dataCells||def.fail.operationInvalid('Axis is already bound.');this.dataCells=def.array.to(dataCells);this.dataCell=this.dataCells[0];this.role=this.dataCell&&this.dataCell.role;this.scaleType=groupingScaleType(this.role.grouping);this._checkRoleCompatibility();return this},isDiscrete:function(){return this.role&&this.role.isDiscrete()},isBound:function(){return!!this.role},setScale:function(scale,noWrap){this.role||def.fail.operationInvalid('Axis is unbound.');this.scale=scale?(noWrap?scale:this._wrapScale(scale)):null;return this},_wrapScale:function(scale){scale.type=this.scaleType;var by;if(scale.type!=='discrete'){var useAbs=this.scaleUsesAbs();var nullAs=this.scaleTreatsNullAs();if(nullAs&&nullAs!=='null'){var nullValue=nullAs==='min'?scale.domain()[0]:0;if(useAbs){by=function(v){return scale(v==null?nullValue:(v<0?-v:v))}}else{by=function(v){return scale(v==null?nullValue:v)}}}else{var nullRangeValue=this.scaleNullRangeValue();if(useAbs){by=function(v){return v==null?nullRangeValue:scale(v<0?-v:v)}}else{by=function(v){return v==null?nullRangeValue:scale(v)}}}}else{by=function(v){return scale(v==null?'':v)}}return def.copy(by,scale)},sceneScale:function(keyArgs){var varName=def.get(keyArgs,'sceneVarName')||this.role.name,grouping=this.role.grouping;if(grouping.isSingleDimension&&grouping.firstDimensionValueType()===Number){var scale=this.scale,nullToZero=def.get(keyArgs,'nullToZero',true);var by=function(scene){var value=scene.vars[varName].value;if(value==null){if(!nullToZero){return value}value=0}return scale(value)};def.copy(by,scale);return by}return this.scale.by1(function(scene){return scene.vars[varName].value})},_checkRoleCompatibility:function(){var L=this.dataCells.length;if(L>1){var grouping=this.role.grouping,i;if(this.scaleType==='discrete'){for(i=1;i1){value=1}return value},value:0.9},BarSizeMax:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyChartOption(optionInfo,'maxBarSize');return true}},cast:function(value){value=pvc.castNumber(value);if(value==null){value=Infinity}else if(value<1){value=1}return value},value:2000},BarStackedMargin:{resolve:'_resolveFull',cast:function(value){value=pvc.castNumber(value);if(value!=null&&value<0){value=0}return value},value:0},OverflowMarkersVisible:{resolve:'_resolveFull',cast:Boolean,value:true},ValuesAnchor:{value:'center'}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BasicSign.js b/pacotes/ccc2/compacto/BasicSign.js deleted file mode 100755 index 2d1e186..0000000 --- a/pacotes/ccc2/compacto/BasicSign.js +++ /dev/null @@ -1 +0,0 @@ -(function(){pv.Mark.prototype.getSign=function(){return this.sign||createBasic(this)};pv.Mark.prototype.getScene=function(){return this.getSign().scene};function createBasic(pvMark){var as=getAncestorSign(pvMark)||def.assert("There must exist an ancestor sign");var bs=new pvc.visual.BasicSign(as.panel,pvMark);var i;var s=pvMark.scene;if(s&&(i=pvMark.index)!=null&&i>=0){bs._buildInstance(pvMark,s[i],true)}return bs}function getAncestorSign(pvMark){var sign;do{pvMark=pvMark.parent}while(pvMark&&!(sign=pvMark.sign)&&(!pvMark.proto||!(sign=pvMark.proto.sign)));return sign}def.type('pvc.visual.BasicSign').init(function(panel,pvMark){this.chart=panel.chart;this.panel=panel;this.pvMark=pvMark;!pvMark.sign||def.assert("Mark already has an attached Sign.");pvMark.sign=this;pvMark.__buildInstance=pvMark.buildInstance;pvMark.buildInstance=this._dispatchBuildInstance}).add({localProperty:function(name,type){this.pvMark.localProperty(name,type);return this},lock:function(name,value){return this.lockMark(name,this._bindWhenFun(value))},optional:function(name,value,tag){return this.optionalMark(name,this._bindWhenFun(value),tag)},lockMark:function(name,value){this.pvMark.lock(name,value);return this},optionalMark:function(name,value,tag){this.pvMark[name](value,tag);return this},delegate:function(dv,tag){return this.pvMark.delegate(dv,tag)},delegateExtension:function(dv){return this.pvMark.delegate(dv,pvc.extensionTag)},hasDelegate:function(tag){return this.pvMark.hasDelegate(tag)},_bindWhenFun:function(value){if(typeof value==='function'){return function(){var sign=this.getSign();return value.apply(sign,arguments)}}return value},_lockDynamic:function(name,method){var me=this;return this.lockMark(name,function(){var sign=this.getSign();var m=sign[method]||me[method]||def.assert("No method with name '"+method+"' is defined");return m.apply(sign,arguments)})},_dispatchBuildInstance:function(instance){this.sign._buildInstance(this,instance)},_buildInstance:function(mark,instance,lateCall){var scene=instance.data;var index=scene?scene.childIndex():0;this.pvInstance=instance;this.scene=scene;this.index=index<0?0:index;scene_renderId.call(scene,mark.renderId());this.state={};if(!lateCall){mark.__buildInstance.call(mark,instance)}}})}()); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BoxPlot.js b/pacotes/ccc2/compacto/BoxPlot.js deleted file mode 100755 index 0709e2c..0000000 --- a/pacotes/ccc2/compacto/BoxPlot.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.BoxPlot',pvc.visual.CategoricalPlot).add({type:'box',_getOptionsDefinition:function(){return pvc.visual.BoxPlot.optionsDef}});pvc.visual.BoxPlot.optionsDef=def.create(pvc.visual.CategoricalPlot.optionsDef,{Stacked:{resolve:null,value:false},OrthoRole:{value:['median','lowerQuartil','upperQuartil','minimum','maximum']},BoxSizeRatio:{resolve:'_resolveFull',cast:function(value){value=pvc.castNumber(value);if(value==null){value=1}else if(value<0.05){value=0.05}else if(value>1){value=1}return value},value:1/3},BoxSizeMax:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyChartOption(optionInfo,'maxBoxSize');return true}},cast:function(value){value=pvc.castNumber(value);if(value==null){value=Infinity}else if(value<1){value=1}return value},value:Infinity}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BoxplotChartTranslationOper.js b/pacotes/ccc2/compacto/BoxplotChartTranslationOper.js deleted file mode 100755 index c4a563c..0000000 --- a/pacotes/ccc2/compacto/BoxplotChartTranslationOper.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.BoxplotChartTranslationOper').add({_configureTypeCore:function(){var autoDimNames=[];var V=this.virtualItemSize();var C=V-this.M;this._getUnboundRoleDefaultDimNames('category',C,autoDimNames);pvc.BoxplotChart.measureRolesNames.forEach(function(roleName){this._getUnboundRoleDefaultDimNames(roleName,1,autoDimNames)},this);autoDimNames.slice(0,this.freeVirtualItemSize());if(autoDimNames.length){this.defReader({names:autoDimNames})}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BulletGroupScene.js b/pacotes/ccc2/compacto/BulletGroupScene.js deleted file mode 100755 index 9a840d3..0000000 --- a/pacotes/ccc2/compacto/BulletGroupScene.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.legend.BulletGroupScene',pvc.visual.Scene).init(function(rootScene,keyArgs){this.base(rootScene,keyArgs);this.extensionPrefix=def.get(keyArgs,'extensionPrefix')||'';this._renderer=def.get(keyArgs,'renderer');this.colorAxis=def.get(keyArgs,'colorAxis');this.clickMode=def.get(keyArgs,'clickMode');if(this.colorAxis&&!this.clickMode){this.clickMode=this.colorAxis.option('LegendClickMode')}}).add({hasRenderer:function(){return this._renderer},renderer:function(renderer){if(renderer!=null){this._renderer=renderer}else{renderer=this._renderer;if(!renderer){var keyArgs;var colorAxis=this.colorAxis;if(colorAxis){keyArgs={drawRule:colorAxis.option('LegendDrawLine'),drawMarker:colorAxis.option('LegendDrawMarker'),markerShape:colorAxis.option('LegendShape')}}renderer=new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs);this._renderer=renderer}}return renderer},itemSceneType:function(){var ItemType=this._itemSceneType;if(!ItemType){ItemType=def.type(pvc.visual.legend.BulletItemScene);var clickMode=this.clickMode;switch(clickMode){case'toggleSelected':ItemType.add(pvc.visual.legend.BulletItemSceneSelection);break;case'toggleVisible':ItemType.add(pvc.visual.legend.BulletItemSceneVisibility);break}this.panel()._extendSceneType('item',ItemType,['isOn','isClickable','click']);this._itemSceneType=ItemType}return ItemType},createItem:function(keyArgs){var ItemType=this.itemSceneType();return new ItemType(this,keyArgs)}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BulletItemDefaultRenderer.js b/pacotes/ccc2/compacto/BulletItemDefaultRenderer.js deleted file mode 100755 index fb28e13..0000000 --- a/pacotes/ccc2/compacto/BulletItemDefaultRenderer.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.legend.BulletItemDefaultRenderer',pvc.visual.legend.BulletItemRenderer).init(function(keyArgs){this.noSelect=def.get(keyArgs,'noSelect',false);this.noHover=def.get(keyArgs,'noHover',false);this.drawRule=def.get(keyArgs,'drawRule',false);if(this.drawRule){this.rulePvProto=def.get(keyArgs,'rulePvProto')}this.drawMarker=!this.drawRule||def.get(keyArgs,'drawMarker',true);if(this.drawMarker){this.markerShape=def.get(keyArgs,'markerShape','square');this.markerPvProto=def.get(keyArgs,'markerPvProto')}}).add({drawRule:false,drawMarker:true,markerShape:null,rulePvProto:null,markerPvProto:null,create:function(legendPanel,pvBulletPanel,extensionPrefix,wrapper){var renderInfo={};var drawRule=this.drawRule;var sceneColorProp=function(scene){return scene.color};if(drawRule){var rulePvBaseProto=new pv.Mark().left(0).top(function(){return this.parent.height()/2}).width(function(){return this.parent.width()}).lineWidth(1,pvc.extensionTag).strokeStyle(sceneColorProp,pvc.extensionTag);if(this.rulePvProto){rulePvBaseProto=this.rulePvProto.extend(rulePvBaseProto)}renderInfo.pvRule=new pvc.visual.Rule(legendPanel,pvBulletPanel,{proto:rulePvBaseProto,noSelect:this.noSelect,noHover:this.noHover,activeSeriesAware:false,extensionId:extensionPrefix+"Rule",wrapper:wrapper}).pvMark}if(this.drawMarker){var markerPvBaseProto=new pv.Mark().left(function(){return this.parent.width()/2}).top(function(){return this.parent.height()/2}).shapeSize(function(){return this.parent.width()},pvc.extensionTag).lineWidth(2,pvc.extensionTag).fillStyle(sceneColorProp,pvc.extensionTag).strokeStyle(sceneColorProp,pvc.extensionTag).shape(this.markerShape,pvc.extensionTag).angle(drawRule?0:Math.PI/2,pvc.extensionTag).antialias(function(){var cos=Math.abs(Math.cos(this.angle()));if(cos!==0&&cos!==1){switch(this.shape()){case'square':case'bar':return false}}return true},pvc.extensionTag);if(this.markerPvProto){markerPvBaseProto=this.markerPvProto.extend(markerPvBaseProto)}renderInfo.pvDot=new pvc.visual.Dot(legendPanel,pvBulletPanel,{proto:markerPvBaseProto,freePosition:true,activeSeriesAware:false,noTooltip:true,noSelect:this.noSelect,noHover:this.noHover,extensionId:extensionPrefix+"Dot",wrapper:wrapper}).pvMark}return renderInfo}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BulletItemRenderer.js b/pacotes/ccc2/compacto/BulletItemRenderer.js deleted file mode 100755 index 81ec2db..0000000 --- a/pacotes/ccc2/compacto/BulletItemRenderer.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.legend.BulletItemRenderer'); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BulletItemScene.js b/pacotes/ccc2/compacto/BulletItemScene.js deleted file mode 100755 index ba64d80..0000000 --- a/pacotes/ccc2/compacto/BulletItemScene.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.legend.BulletItemScene',pvc.visual.Scene).init(function(bulletGroup,keyArgs){this.base(bulletGroup,keyArgs);var value,rawValue,label;if(keyArgs){value=keyArgs.value;rawValue=keyArgs.rawValue;label=keyArgs.label}if(value===undefined){var source=this.group||this.datum;if(source){value=source.value;rawValue=source.rawValue;label=source.ensureLabel();var dataPartDim=this.chart()._getDataPartDimName();if(dataPartDim){var dataPartAtom=source.atoms[dataPartDim];if(isNaN(+dataPartAtom.value)){label+=" ("+dataPartAtom.label+")"}}}}this.vars.value=new pvc.visual.ValueLabelVar(value||null,label||"",rawValue)}).add({isOn:function(){return true},isClickable:function(){return false},click:function(){},labelTextSize:function(){var valueVar=this.vars.value;return valueVar&&pv.Text.measure(valueVar.label,this.vars.font)}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BulletItemSceneSelection.js b/pacotes/ccc2/compacto/BulletItemSceneSelection.js deleted file mode 100755 index 5f4e22d..0000000 --- a/pacotes/ccc2/compacto/BulletItemSceneSelection.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.legend.BulletItemSceneSelection').add({isOn:function(){var owner=(this.group||this.datum).owner;return!owner.selectedCount()||this.datums().any(function(datum){return!datum.isNull&&datum.isSelected})},isClickable:function(){return this.chart()._canSelectWithClick()},click:function(){var datums=this.datums().array();if(datums.length){var chart=this.chart();chart._updatingSelections(function(){datums=chart._onUserSelection(datums);if(datums){var on=def.query(datums).any(function(datum){return datum.isSelected});pvc.data.Data.setSelected(datums,!on)}})}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BulletItemSceneVisibility.js b/pacotes/ccc2/compacto/BulletItemSceneVisibility.js deleted file mode 100755 index 245240e..0000000 --- a/pacotes/ccc2/compacto/BulletItemSceneVisibility.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.legend.BulletItemSceneVisibility').add({isOn:function(){return this.datums().any(function(datum){return!datum.isNull&&datum.isVisible})},isClickable:function(){return true},click:function(){if(pvc.data.Data.toggleVisible(this.datums())){this.chart().render(true,true,false)}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BulletPlot.js b/pacotes/ccc2/compacto/BulletPlot.js deleted file mode 100755 index f20b3b9..0000000 --- a/pacotes/ccc2/compacto/BulletPlot.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.BulletPlot',pvc.visual.Plot).add({type:'bullet',_getOptionsDefinition:function(){return pvc.visual.BulletPlot.optionsDef}});pvc.visual.BulletPlot.optionsDef=def.create(pvc.visual.Plot.optionsDef,{ValuesVisible:{value:true},ColorRole:{value:null}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/BulletRootScene.js b/pacotes/ccc2/compacto/BulletRootScene.js deleted file mode 100755 index b10569a..0000000 --- a/pacotes/ccc2/compacto/BulletRootScene.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.legend.BulletRootScene',pvc.visual.Scene).init(function(parent,keyArgs){this.base(parent,keyArgs);var markerDiam=def.get(keyArgs,'markerSize',15);var itemPadding=new pvc.Sides(def.get(keyArgs,'itemPadding',5)).resolve(markerDiam,markerDiam);def.set(this.vars,'horizontal',def.get(keyArgs,'horizontal',false),'font',def.get(keyArgs,'font'),'markerSize',markerDiam,'textMargin',def.get(keyArgs,'textMargin',6),'itemPadding',itemPadding)}).add({layout:function(layoutInfo){var clientSize=layoutInfo.clientSize;if(!(clientSize.width>0&&clientSize.height>0)){return new pvc.Size(0,0)}var desiredClientSize=layoutInfo.desiredClientSize;var markerDiam=this.vars.markerSize;var textLeft=markerDiam+this.vars.textMargin;var itemPadding=this.vars.itemPadding;var a_width=this.vars.horizontal?'width':'height';var a_height=pvc.BasePanel.oppositeLength[a_width];var maxRowWidth=desiredClientSize[a_width];if(!maxRowWidth||maxRowWidth<0){maxRowWidth=clientSize[a_width]}var row;var rows=[];var contentSize={width:0,height:0};this.childNodes.forEach(function(groupScene){groupScene.childNodes.forEach(layoutItem,this)},this);if(!row){return new pvc.Size(0,0)}commitRow(true);def.set(this.vars,'rows',rows,'rowCount',row,'size',contentSize);var isV1Compat=this.compatVersion()<=1;var w=isV1Compat?maxRowWidth:contentSize.width;var h=desiredClientSize[a_height];if(!h||h<0){h=contentSize.height}return def.set({},a_width,Math.min(w,clientSize[a_width]),a_height,Math.min(h,clientSize[a_height]));function layoutItem(itemScene){var textSize=itemScene.labelTextSize();var hidden=!textSize||!textSize.width||!textSize.height;itemScene.isHidden=hidden;if(hidden){return}var widthMargin=0;var itemClientSize={width:textLeft+textSize.width+widthMargin,height:Math.max(textSize.height,markerDiam)};var isFirstInRow;if(!row){row=new pvc.visual.legend.BulletItemSceneRow(0);isFirstInRow=true}else{isFirstInRow=!row.items.length}var newRowWidth=row.size.width+itemClientSize[a_width];if(!isFirstInRow){newRowWidth+=itemPadding[a_width]}if(!isFirstInRow&&(newRowWidth>maxRowWidth)){commitRow(false);newRowWidth=itemClientSize[a_width]}var rowSize=row.size;rowSize.width=newRowWidth;rowSize.height=Math.max(rowSize.height,itemClientSize[a_height]);var rowItemIndex=row.items.length;row.items.push(itemScene);def.set(itemScene.vars,'row',row,'rowIndex',rowItemIndex,'clientSize',itemClientSize)}function commitRow(isLast){var rowSize=row.size;contentSize.height+=rowSize.height;if(rows.length){contentSize.height+=itemPadding[a_height]}contentSize.width=Math.max(contentSize.width,rowSize.width);rows.push(row);if(!isLast){row=new pvc.visual.legend.BulletItemSceneRow(rows.length)}}},defaultGroupSceneType:function(){var GroupType=this._bulletGroupType;if(!GroupType){GroupType=def.type(pvc.visual.legend.BulletGroupScene);this._bulletGroupType=GroupType}return GroupType},createGroup:function(keyArgs){var GroupType=this.defaultGroupSceneType();return new GroupType(this,keyArgs)}});def.type('pvc.visual.legend.BulletItemSceneRow').init(function(index){this.index=index;this.items=[];this.size={width:0,height:0}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/CartesianAxis.js b/pacotes/ccc2/compacto/CartesianAxis.js deleted file mode 100755 index 7acbb71..0000000 --- a/pacotes/ccc2/compacto/CartesianAxis.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){var $VA=pvc.visual.Axis;def.type('pvc.visual.CartesianAxis',$VA).init(function(chart,type,index,keyArgs){var options=chart.options;this.orientation=$VCA.getOrientation(type,options.orientation);this.orientedId=$VCA.getOrientedId(this.orientation,index);if(chart._allowV1SecondAxis&&index===1){this.v1SecondOrientedId='second'+this.orientation.toUpperCase()}this.base(chart,type,index,keyArgs);var extensions=this.extensionPrefixes=[this.id+'Axis',this.orientedId+'Axis'];if(this.v1SecondOrientedId){extensions.push(this.v1SecondOrientedId+'Axis')}this._extPrefAxisPosition=extensions.length;extensions.push('axis')}).add({bind:function(dataCells){this.base(dataCells);this._syncExtensionPrefixes();return this},_syncExtensionPrefixes:function(){var extensions=this.extensionPrefixes;extensions.length=this._extPrefAxisPosition;var st=this.scaleType;if(st){extensions.push(st+'Axis');if(st!=='discrete'){extensions.push('continuousAxis')}}extensions.push('axis')},setScale:function(scale){var oldScale=this.scale;this.base(scale);if(oldScale){delete this.domain;delete this.ticks;delete this._roundingPaddings}if(scale){if(!scale.isNull&&this.scaleType!=='discrete'){this.domain=scale.domain();this.domain.minLocked=!!scale.minLocked;this.domain.maxLocked=!!scale.maxLocked;if(this.scaleType==='numeric'){var roundMode=this.option('DomainRoundMode');if(roundMode==='nice'){scale.nice()}var tickFormatter=this.option('TickFormatter');if(tickFormatter){scale.tickFormatter(tickFormatter)}}}}return this},setTicks:function(ticks){var scale=this.scale;(scale&&!scale.isNull)||def.fail.operationInvalid("Scale must be set and non-null.");this.ticks=ticks;if(scale.type==='numeric'&&this.option('DomainRoundMode')==='tick'){delete this._roundingPaddings;var tickCount=ticks&&ticks.length;if(tickCount){this.scale.domain(ticks[0],ticks[tickCount-1])}else{this.scale.domain(this.domain[0],this.domain[1])}}},setScaleRange:function(size){var scale=this.scale;scale.min=0;scale.max=size;scale.size=size;if(scale.type==='discrete'){if(scale.domain().length>0){var bandRatio=this.chart.options.panelSizeRatio||0.8;scale.splitBandedCenter(scale.min,scale.max,bandRatio)}}else{scale.range(scale.min,scale.max)}if(pvc.debug>4){this.chart._log("Axis "+this.id+" setRange: "+pvc.stringify(scale.range()))}return scale},getScaleRoundingPaddings:function(){var roundingPaddings=this._roundingPaddings;if(!roundingPaddings){roundingPaddings={begin:0,end:0,beginLocked:false,endLocked:false};var scale=this.scale;if(scale&&!scale.isNull&&scale.type!=='discrete'){var originalDomain=this.domain;roundingPaddings.beginLocked=originalDomain.minLocked;roundingPaddings.endLocked=originalDomain.maxLocked;if(scale.type==='numeric'&&this.option('DomainRoundMode')!=='none'){var currDomain=scale.domain();var origDomain=this.domain||def.assert("Original domain must be set");var currLength=currDomain[1]-currDomain[0];if(currLength){var diff=origDomain[0]-currDomain[0];if(diff>0){roundingPaddings.begin=diff/currLength}diff=currDomain[1]-origDomain[1];if(diff>0){roundingPaddings.end=diff/currLength}}}}this._roundingPaddings=roundingPaddings}return roundingPaddings},_getOptionsDefinition:function(){return cartAxis_optionsDef},_buildOptionId:function(){return this.id+"Axis"},_registerResolversNormal:function(rs,keyArgs){if(this.chart.compatVersion()<=1){rs.push(this._resolveByV1OnlyLogic)}rs.push(this._resolveByOptionId,this._resolveByOrientedId);if(this.index===1){rs.push(this._resolveByV1OptionId)}rs.push(this._resolveByScaleType,this._resolveByCommonId)},_resolveByOrientedId:pvc.options.specify(function(optionInfo){return this._chartOption(this.orientedId+"Axis"+optionInfo.name)}),_resolveByV1OptionId:pvc.options.specify(function(optionInfo){return this._chartOption('secondAxis'+optionInfo.name)}),_resolveByScaleType:pvc.options.specify(function(optionInfo){var st=this.scaleType;if(st){var name=optionInfo.name;var value=this._chartOption(st+'Axis'+name);if(value===undefined&&st!=='discrete'){value=this._chartOption('continuousAxis'+name)}return value}}),_resolveByCommonId:pvc.options.specify(function(optionInfo){return this._chartOption('axis'+optionInfo.name)})});var $VCA=pvc.visual.CartesianAxis;$VCA.getOrientation=function(type,chartOrientation){return((type==='base')===(chartOrientation==='vertical'))?'x':'y'};$VCA.getOrientedId=function(orientation,index){if(index===0){return orientation}return orientation+(index+1)};var fixedMinMaxSpec={resolve:'_resolveFull',data:{resolveV1:function(optionInfo){if(!this.index&&this.type==='ortho'){this._specifyChartOption(optionInfo,this.id+optionInfo.name)}return true}},cast:pvc.castNumber};function castDomainScope(scope,axis){return pvc.parseDomainScope(scope,axis.orientation)}function castAxisPosition(side){if(side){if(def.hasOwn(pvc.Sides.namesSet,side)){var mapAlign=pvc.BasePanel[this.orientation==='y'?'horizontalAlign':'verticalAlign2'];return mapAlign[side]}if(pvc.debug>=2){pvc.log(def.format("Invalid axis position value '{0}'.",[side]))}}return this.orientation==='x'?'bottom':'left'}var normalV1Data={resolveV1:function(optionInfo){if(!this.index){if(this._resolveByOrientedId(optionInfo)){return true}}else if(this._resolveByV1OptionId(optionInfo)){return true}this._resolveDefault(optionInfo);return true}};var defaultPosition=pvc.options.defaultValue(function(optionInfo){if(!this.typeIndex){return this.orientation==='x'?'bottom':'left'}var firstAxis=this.chart.axesByType[this.type].first;var position=firstAxis.option('Position');return pvc.BasePanel.oppositeAnchor[position]});function castSize(value){var position=this.option('Position');return pvc.Size.toOrtho(value,position)}function castTitleSize(value){var position=this.option('Position');return pvc.Size.to(value,{singleProp:pvc.BasePanel.orthogonalLength[position]})}var cartAxis_optionsDef=def.create(axis_optionsDef,{Visible:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){if(this.index<=1){var v1OptionId=this.index===0?def.firstUpperCase(this.orientation):'Second';this._specifyChartOption(optionInfo,'show'+v1OptionId+'Scale')}return true}},cast:Boolean,value:true},Composite:{resolve:function(optionInfo){if(this.index>0){optionInfo.specify(false);return true}return this._resolveFull(optionInfo)},data:{resolveV1:function(optionInfo){this._specifyChartOption(optionInfo,'useCompositeAxis');return true}},cast:Boolean,value:false},Size:{resolve:'_resolveFull',data:normalV1Data,cast:castSize},SizeMax:{resolve:'_resolveFull',cast:castSize},Position:{resolve:'_resolveFull',data:{resolveV1:normalV1Data.resolveV1,resolveDefault:defaultPosition},cast:castAxisPosition},FixedMin:fixedMinMaxSpec,FixedMax:fixedMinMaxSpec,OriginIsZero:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){switch(this.index){case 0:this._specifyChartOption(optionInfo,'originIsZero');break;case 1:if(this.chart._allowV1SecondAxis){this._specifyChartOption(optionInfo,'secondAxisOriginIsZero')}break}return true}},cast:Boolean,value:true},DomainScope:{resolve:'_resolveFull',cast:castDomainScope,value:'global'},Offset:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){switch(this.index){case 0:this._specifyChartOption(optionInfo,'axisOffset');break;case 1:if(this.chart._allowV1SecondAxis){this._specifyChartOption(optionInfo,'secondAxisOffset');break}break}return true}},cast:pvc.castNumber},LabelSpacingMin:{resolve:'_resolveFull',cast:pvc.castNumber},OverlappedLabelsMode:{resolve:'_resolveFull',cast:pvc.parseOverlappedLabelsMode,value:'hide'},Grid:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){if(!this.index){this._specifyChartOption(optionInfo,this.orientation+'AxisFullGrid')}return true}},cast:Boolean,value:false},GridCrossesMargin:{resolve:'_resolveFull',cast:Boolean,value:true},EndLine:{resolve:'_resolveFull',cast:Boolean},ZeroLine:{resolve:'_resolveFull',cast:Boolean,value:true},RuleCrossesMargin:{resolve:'_resolveFull',cast:Boolean,value:true},Ticks:{resolve:'_resolveFull',cast:Boolean},DesiredTickCount:{resolve:'_resolveFull',data:{resolveV1:normalV1Data.resolveV1,resolveDefault:function(optionInfo){if(this.chart.compatVersion()<=1){optionInfo.defaultValue(5);return true}}},cast:pvc.castNumber},MinorTicks:{resolve:'_resolveFull',data:normalV1Data,cast:Boolean,value:true},TickFormatter:{resolve:'_resolveFull',cast:def.fun.as},DomainRoundMode:{resolve:'_resolveFull',data:{resolveV1:normalV1Data.resolveV1,resolveDefault:function(optionInfo){if(this.chart.compatVersion()<=1){optionInfo.defaultValue('none');return true}}},cast:pvc.parseDomainRoundingMode,value:'tick'},TickExponentMin:{resolve:'_resolveFull',cast:pvc.castNumber},TickExponentMax:{resolve:'_resolveFull',cast:pvc.castNumber},Title:{resolve:'_resolveFull',cast:String},TitleSize:{resolve:'_resolveFull',cast:castTitleSize},TitleSizeMax:{resolve:'_resolveFull',cast:castTitleSize},TitleFont:{resolve:'_resolveFull',cast:String},TitleMargins:{resolve:'_resolveFull',cast:pvc.Sides.as},TitlePaddings:{resolve:'_resolveFull',cast:pvc.Sides.as},TitleAlign:{resolve:'_resolveFull',cast:function castAlign(align){var position=this.option('Position');return pvc.parseAlign(position,align)}},Font:{resolve:'_resolveFull',cast:String},ClickAction:{resolve:'_resolveFull',data:normalV1Data},DoubleClickAction:{resolve:'_resolveFull',data:normalV1Data}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/CartesianAxisRootScene.js b/pacotes/ccc2/compacto/CartesianAxisRootScene.js deleted file mode 100755 index 6ae058b..0000000 --- a/pacotes/ccc2/compacto/CartesianAxisRootScene.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.CartesianAxisRootScene',pvc.visual.Scene); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/CartesianAxisTickScene.js b/pacotes/ccc2/compacto/CartesianAxisTickScene.js deleted file mode 100755 index a48da8a..0000000 --- a/pacotes/ccc2/compacto/CartesianAxisTickScene.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.CartesianAxisTickScene',pvc.visual.Scene).init(function(parent,keyArgs){this.base(parent,keyArgs);this.vars.tick=new pvc.visual.ValueLabelVar(def.get(keyArgs,'tick'),def.get(keyArgs,'tickLabel'),def.get(keyArgs,'tickRaw'))}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/CartesianFocusWindow.js b/pacotes/ccc2/compacto/CartesianFocusWindow.js deleted file mode 100755 index 9800795..0000000 --- a/pacotes/ccc2/compacto/CartesianFocusWindow.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.CartesianFocusWindow',pvc.visual.OptionsBase).init(function(chart){this.base(chart,'focusWindow',0,{byNaked:false});var baseAxis=chart.axes.base;this.base=new pvc.visual.CartesianFocusWindowAxis(this,baseAxis)}).add({_getOptionsDefinition:function(){return focusWindow_optionsDef},_exportData:function(){return{base:def.copyProps(this.base,pvc.visual.CartesianFocusWindow.props)}},_importData:function(data){var baseData=data.base;this.base.option.specify({Begin:baseData.begin,End:baseData.end,Length:baseData.length})},_initFromOptions:function(){this.base._initFromOptions()},_onAxisChanged:function(axis){var changed=this.option('Changed');if(changed){changed.call(this.chart.basePanel._getContext())}}});var focusWindow_optionsDef=def.create(axis_optionsDef,{Changed:{resolve:'_resolveFull',cast:def.fun.as}});def.type('pvc.visual.CartesianFocusWindowAxis',pvc.visual.OptionsBase).init(function(fw,axis){this.window=fw;this.axis=axis;this.isDiscrete=axis.isDiscrete();this.base(axis.chart,'focusWindow'+def.firstUpperCase(axis.type),0,{byNaked:false})}).addStatic({props:['begin','end','length']}).add({_getOptionsDefinition:function(){return focusWindowAxis_optionsDef},_initFromOptions:function(){var o=this.option;this.set({begin:o('Begin'),end:o('End'),length:o('Length')})},set:function(keyArgs){var me=this;var render=def.get(keyArgs,'render');var select=def.get(keyArgs,'select',true);var b,e,l;keyArgs=me._readArgs(keyArgs);if(!keyArgs){if(this.begin!=null&&this.end!=null&&this.length!=null){return}}else{b=keyArgs.begin;e=keyArgs.end;l=keyArgs.length}var axis=me.axis;var scale=axis.scale;var isDiscrete=me.isDiscrete;var contCast=!isDiscrete?axis.role.firstDimensionType().cast:null;var domain=scale.domain();var a,L;if(isDiscrete){L=domain.length;var ib,ie,ia;if(b!=null){var nb=+b;if(!isNaN(nb)){if(nb===Infinity){ib=L-1;b=domain[ib]}else if(nb===-Infinity){ib=0;b=domain[ib]}}if(ib==null){ib=domain.indexOf(''+b);if(ib<0){ib=0;b=domain[ib]}}}if(e!=null){var ne=+e;if(!isNaN(ne)){if(ne===Infinity){ie=L-1;e=domain[ie]}else if(ne===-Infinity){ie=0;e=domain[ie]}}if(ie==null){ie=domain.indexOf(''+e);if(ie<0){ie=L-1;e=domain[ie]}}}if(l!=null){l=+l;if(isNaN(l)){l=null}else if(l<0&&(b!=null||e!=null)){a=b;ia=ib;b=e,ib=ie,e=a,ie=ia;l=-l}}if(b!=null){if(e!=null){if(ib>ie){a=b;ia=ib;b=e,ib=ie,e=a,ie=ia}l=ie-ib+1}else{if(l==null){l=L-ib}ie=ib+l-1;if(ie>L-1){ie=L-1;l=ie-ib+1}e=domain[ie]}}else{if(e!=null){if(l==null){l=ie}ib=ie-l+1;if(ib<0){ib=0;l=ie-ib+1}b=domain[ib]}else{if(l==null){l=Math.max(~~(L/3),1); }if(l>L){l=L;ib=0;ie=L-1}else{ia=~~(L/2); ib=ia-~~(l/2);ie=ib+l-1}b=domain[ib];e=domain[ie]}}}else{if(l!=null){l=+l;if(isNaN(l)){l=null}else if(l<0&&(b!=null||e!=null)){a=b;b=e,e=a;l=-l}}var min=domain[0];var max=domain[1];L=max-min;if(b!=null){if(bmax){b=max}}if(e!=null){if(emax){e=max}}if(b!=null){if(e!=null){if(b>e){a=b;b=e,e=a}l=e-b}else{if(l==null){l=max-b}e=b+l;if(e>max){e=max;l=e-b}}}else{if(e!=null){if(l==null){l=e-min}b=e-l;if(bL){l=L;b=min;e=max}else{a=~~(L/2); b=a-~~(l/2);e=(+b)+(+l)}}}b=contCast(b);e=contCast(e);l=contCast(l);var constraint=me.option('Constraint');if(constraint){var oper2={type:'new',target:'begin',value:b,length:l,length0:l,min:min,max:max,minView:min,maxView:max};constraint(oper2);b=contCast(oper2.value);l=contCast(oper2.length);e=contCast((+b)+(+l))}}me._set(b,e,l,select,render)},_updatePosition:function(pbeg,pend,select,render){var me=this;var axis=me.axis;var scale=axis.scale;var b,e,l;if(me.isDiscrete){var ib=scale.invertIndex(pbeg);var ie=scale.invertIndex(pend)-1;var domain=scale.domain();b=domain[ib];e=domain[ie];l=ie-ib+1}else{b=scale.invert(pbeg);e=scale.invert(pend);l=e-b}this._set(b,e,l,select,render)},_constraintPosition:function(oper){var me=this;var axis=me.axis;var scale=axis.scale;var constraint;if(me.isDiscrete){var index=Math.floor(scale.invertIndex(oper.point,true));if(index>=0){var r=scale.range();var L=scale.domain().length;var S=(r.max-r.min)/L;if(index>=L&&(oper.type==='new'||oper.type==='resize-begin')){index=L-1}oper.point=index*S}}else if((constraint=me.option('Constraint'))){var contCast=axis.role.firstDimensionType().cast;var v=contCast(scale.invert(oper.point));var sign=oper.target==='begin'?1:-1;var pother=oper.point+sign*oper.length;var vother=contCast(scale.invert(pother));var vlength=contCast(sign*(vother-v));var vlength0,pother0,vother0;if(oper.length===oper.length0){vlength0=vlength}else{pother0=oper.point+sign*oper.length0;vother0=contCast(scale.invert(pother0));vlength0=sign*(vother0-v)}var vmin=contCast(scale.invert(oper.min));var vmax=contCast(scale.invert(oper.max));var oper2={type:oper.type,target:oper.target,value:v,length:vlength,length0:vlength0,min:vmin,max:vmax,minView:contCast(scale.invert(oper.minView)),maxView:contCast(scale.invert(oper.maxView))};constraint(oper2);if(+oper2.value!==+v){v=oper2.value;oper.point=scale(v)}var vlength2=oper2.length;if(+vlength2!==+vlength){if(+vlength2===+vlength0){oper.length=oper.length0}else{var vother2=(+v)+sign*(+vlength2);var pother2=scale(vother2);oper.length=pother2-sign*oper.point}}if(+oper2.min!==+vmin){oper.min=scale(oper2.min)}if(+oper2.max!==+vmax){oper.max=scale(oper2.max)}}},_compare:function(a,b){return this.isDiscrete?((''+a)===(''+b)):((+a)===(+b))},_set:function(b,e,l,select,render){var me=this;var changed=false;if(!me._compare(b,me.begin)){me.begin=b;changed=true}if(!me._compare(e,me.end)){me.end=e;changed=true}if(!me._compare(l,me.length)){me.length=l;changed=true}if(changed){me.window._onAxisChanged(this)}if(select){me._updateSelection({render:render})}return changed},_readArgs:function(keyArgs){if(keyArgs){var out={};var any=0;var read=function(p){var v=keyArgs[p];if(v!=null){any=true}else{v=this[p]}out[p]=v};pvc.visual.CartesianFocusWindowAxis.props.forEach(read,this);if(any){return out}}},_updateSelection:function(keyArgs){var me=this;var selectDatums;var axis=me.axis;var isDiscrete=axis.isDiscrete();var chart=axis.chart;var dataCell=axis.dataCell;var role=dataCell.role;var partData=chart.partData(dataCell.dataPartValue,{visible:true});var domainData;if(isDiscrete){domainData=partData.flattenBy(role);var dataBegin=domainData._childrenByKey[me.begin];var dataEnd=domainData._childrenByKey[me.end];if(dataBegin&&dataEnd){var indexBegin=dataBegin.childIndex();var indexEnd=dataEnd.childIndex();selectDatums=def.range(indexBegin,indexEnd-indexBegin+1).select(function(index){return domainData._children[index]}).selectMany(function(data){return data._datums}).distinct(function(datum){return datum.key})}}else{domainData=partData;var dimName=role.firstDimensionName();selectDatums=def.query(partData._datums).where(function(datum){var v=datum.atoms[dimName].value;return v!=null&&v>=me.begin&&v<=me.end})}if(selectDatums){chart.data.replaceSelected(selectDatums);chart.root.updateSelections(keyArgs)}}});var focusWindowAxis_optionsDef=def.create(axis_optionsDef,{Resizable:{resolve:'_resolveFull',cast:Boolean,value:true},Movable:{resolve:'_resolveFull',cast:Boolean,value:true},Begin:{resolve:'_resolveFull'},End:{resolve:'_resolveFull'},Length:{resolve:'_resolveFull'},Constraint:{resolve:'_resolveFull',cast:def.fun.as}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/CartesianPlot.js b/pacotes/ccc2/compacto/CartesianPlot.js deleted file mode 100755 index d4d80cb..0000000 --- a/pacotes/ccc2/compacto/CartesianPlot.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.CartesianPlot',pvc.visual.Plot).add({_getOptionsDefinition:function(){return pvc.visual.CartesianPlot.optionsDef}});function castTrend(trend){if(this.name==='trend'){return null}var type=this.option('TrendType');if(!type&&trend){type=trend.type}if(!type||type==='none'){return null}if(!trend){trend={}}else{trend=Object.create(trend)}trend.type=type;var label=this.option('TrendLabel');if(label!==undefined){trend.label=label}return trend}pvc.visual.CartesianPlot.optionsDef=def.create(pvc.visual.Plot.optionsDef,{BaseAxis:{value:1},BaseRole:{resolve:'_resolveFixed',cast:String},OrthoAxis:{resolve:function(optionInfo){if(this.globalIndex===0){optionInfo.specify(1);return true}return this._resolveFull(optionInfo)},data:{resolveV1:function(optionInfo){if(this.name==='plot2'&&this.chart._allowV1SecondAxis&&this._chartOption('secondAxisIndependentScale')){optionInfo.specify(2)}return true}},cast:function(value){value=pvc.castNumber(value);if(value!=null){value=def.between(value,1,10)}else{value=1}return value},value:1},OrthoRole:{resolve:pvc.options.resolvers(['_resolveFixed','_resolveDefault'])},Trend:{resolve:'_resolveFull',data:{resolveDefault:function(optionInfo){var type=this.option('TrendType');if(type){optionInfo.defaultValue({type:type});return true}}},cast:castTrend},TrendType:{resolve:'_resolveFull',cast:pvc.parseTrendType},TrendLabel:{resolve:'_resolveFull',cast:String},NullInterpolationMode:{resolve:'_resolveFull',cast:pvc.parseNullInterpolationMode,value:'none'}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/CategoricalPlot.js b/pacotes/ccc2/compacto/CategoricalPlot.js deleted file mode 100755 index 25b400d..0000000 --- a/pacotes/ccc2/compacto/CategoricalPlot.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.CategoricalPlot',pvc.visual.CartesianPlot).add({_getOptionsDefinition:function(){return pvc.visual.CategoricalPlot.optionsDef}});pvc.visual.CategoricalPlot.optionsDef=def.create(pvc.visual.CartesianPlot.optionsDef,{Stacked:{resolve:'_resolveFull',cast:Boolean,value:false},BaseRole:{value:'category'},OrthoRole:{value:'value'}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/ColorAxis.js b/pacotes/ccc2/compacto/ColorAxis.js deleted file mode 100755 index 304bfb8..0000000 --- a/pacotes/ccc2/compacto/ColorAxis.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.ColorAxis',pvc.visual.Axis).add({scaleNullRangeValue:function(){return this.option('Missing')||null},scaleUsesAbs:function(){return this.option('UseAbs')},bind:function(dataCells){this.base(dataCells);this._plotList=def.query(dataCells).select(function(dataCell){return dataCell.plot}).distinct(function(plot){return plot&&plot.id}).array();return this},calculateScale:function(){var scale,noWrap;var dataCells=this.dataCells;if(dataCells){var chart=this.chart;if(this.scaleType==='discrete'){var domainValues=def.query(dataCells).selectMany(function(dataCell){var role=dataCell.role;if(role&&role.isBound()){var partData=chart.partData(dataCell.dataPartValue);var domainData=partData&&partData.flattenBy(role);dataCell.data=domainData;return domainData&&domainData.children()}}).distinct(function(child){return child.key}).select(function(child){return def.nullyTo(child.value,'')}).array();this.domainValues=domainValues;scale=this.scheme()(domainValues);noWrap=true}else{if(dataCells.length===1){var visibleDomainData=chart.root.visibleData(this.dataCell.dataPartValue);var normByCateg=this.option('NormByCategory');var scaleOptions={type:this.option('ScaleType'),colors:this.option('Colors')().range(),colorDomain:this.option('Domain'),colorMin:this.option('Min'),colorMax:this.option('Max'),colorNull:this.option('Missing'),data:visibleDomainData,colorDimension:this.role.firstDimensionName(),normPerBaseCategory:normByCateg};if(normByCateg){this.scalesByCateg=pvc.color.scales(scaleOptions)}else{scale=pvc.color.scale(scaleOptions)}}}}this.setScale(scale,noWrap);return this},_wrapScale:function(scale){var applyTransf;if(this.scaleType==='discrete'){applyTransf=this.option.isSpecified('Transform')||(!this.option.isSpecified('Colors')&&!this.option.isSpecified('Map'))}else{applyTransf=true}if(applyTransf){var colorTransf=this.option('Transform');if(colorTransf){scale=scale.transform(colorTransf)}}return this.base(scale)},scheme:function(){return def.lazy(this,'_scheme',this._createScheme,this)},_createColorMapFilter:function(colorMap){var fixedColors=def.uniqueIndex(colorMap,function(c){return c.key});return{domain:function(k){return!def.hasOwn(colorMap,k)},color:function(c){return!def.hasOwn(fixedColors,c.key)}}},_createScheme:function(){var me=this;var baseScheme=me.option('Colors');if(me.scaleType!=='discrete'){return function(d){var scale=baseScheme.apply(null,arguments);return me._wrapScale(scale)}}var colorMap=me.option('Map');if(!colorMap){return function(d){var scale=baseScheme.apply(null,arguments);return me._wrapScale(scale)}}var filter=this._createColorMapFilter(colorMap);return function(d){var scale;if(!(d instanceof Array)){d=def.array.copy(arguments)}d=d.filter(filter.domain);var baseScale=baseScheme(d);var r=baseScale.range().filter(filter.color);baseScale.range(r);scale=function(k){var c=def.getOwn(colorMap,k);return c||baseScale(k)};def.copy(scale,baseScale);var dx,rx;scale.domain=function(){if(arguments.length){throw def.operationInvalid("The scale cannot be modified.")}if(!dx){dx=def.array.append(def.ownKeys(colorMap),d)}return dx};scale.range=function(){if(arguments.length){throw def.operationInvalid("The scale cannot be modified.")}if(!rx){rx=def.array.append(def.own(colorMap),d)}return rx};return me._wrapScale(scale)}},sceneScale:function(keyArgs){var varName=def.get(keyArgs,'sceneVarName')||this.role.name;return this.scale.by1(function(scene){return scene.vars[varName].value})},_buildOptionId:function(){return this.id+"Axis"},_getOptionsDefinition:function(){return colorAxis_optionsDef},_resolveByNaked:pvc.options.specify(function(optionInfo){if(!this.index){return this._chartOption(this.id+def.firstUpperCase(optionInfo.name))}}),_specifyV1ChartOption:function(optionInfo,asName){if(!this.index&&this.chart.compatVersion()<=1&&this._specifyChartOption(optionInfo,asName)){return true}}});function castSize(size){if(!def.object.is(size)){var position=this.option('Position');size=new pvc.Size().setSize(size,{singleProp:pvc.BasePanel.orthogonalLength[position]})}return size}function castAlign(align){var position=this.option('Position');return pvc.parseAlign(position,align)}function castColorMap(colorMap){var resultMap;if(colorMap){var any;def.eachOwn(colorMap,function(v,k){any=true;colorMap[k]=pv.color(v)});if(any){resultMap=colorMap}}return resultMap}var legendData={resolveDefault:function(optionInfo){if(!this.index&&this._specifyChartOption(optionInfo,def.firstLowerCase(optionInfo.name))){return true}}};function getDefaultColor(optionInfo){var colors;if(this.scaleType==='discrete'){if(this.index===0){colors=pvc.createColorScheme()}else{var me=this;colors=function(){return me.chart._getRoleColorScale(me.role.name)}}}else{colors=['red','yellow','green'].map(function(name){return pv.Color.names[name]})}return colors}var colorAxis_optionsDef=def.create(axis_optionsDef,{Colors:{resolve:'_resolveFull',getDefault:getDefaultColor,data:{resolveV1:function(optionInfo){if(this.scaleType==='discrete'){if(this.index===0){this._specifyChartOption(optionInfo,'colors')}else if(this.index===1&&this.chart._allowV1SecondAxis){this._specifyChartOption(optionInfo,'secondAxisColor')}}else{this._specifyChartOption(optionInfo,'colorRange')}return true},resolveDefault:function(optionInfo){if(this.index===0){this._specifyChartOption(optionInfo,'colors')}}},cast:pvc.colorScheme},Map:{resolve:'_resolveFull',cast:castColorMap},Transform:{resolve:'_resolveFull',data:{resolveDefault:function(optionInfo){var plotList=this._plotList;if(plotList.length<=2){var onlyTrendAndPlot2=def.query(plotList).all(function(plot){var name=plot.name;return(name==='plot2'||name==='trend')});if(onlyTrendAndPlot2){optionInfo.defaultValue(pvc.brighterColorTransform);return true}}}},cast:def.fun.to},NormByCategory:{resolve:function(optionInfo){if(!this.chart._allowColorPerCategory){optionInfo.specify(false);return true}return this._resolveFull(optionInfo)},data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'normPerBaseCategory');return true}},cast:Boolean,value:false},ScaleType:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'scalingType');return true}},cast:pvc.parseContinuousColorScaleType,value:'linear'},UseAbs:{resolve:'_resolveFull',cast:Boolean,value:false},Domain:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'colorRangeInterval');return true}},cast:def.array.to},Min:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'minColor');return true}},cast:pv.color},Max:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'maxColor');return true}},cast:pv.color},Missing:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){this._specifyV1ChartOption(optionInfo,'nullColor');return true}},cast:pv.color,value:pv.color("#efc5ad")},LegendVisible:{resolve:'_resolveFull',data:legendData,cast:Boolean,value:true},LegendClickMode:{resolve:'_resolveFull',data:legendData,cast:pvc.parseLegendClickMode,value:'toggleVisible'},LegendDrawLine:{resolve:'_resolveFull',data:legendData,cast:Boolean,value:false},LegendDrawMarker:{resolve:'_resolveFull',data:legendData,cast:Boolean,value:true},LegendShape:{resolve:'_resolveFull',data:legendData,cast:pvc.parseShape}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Complex.js b/pacotes/ccc2/compacto/Complex.js deleted file mode 100755 index c74af31..0000000 --- a/pacotes/ccc2/compacto/Complex.js +++ /dev/null @@ -1 +0,0 @@ -var complex_nextId=1;def.type('pvc.data.Complex').init(function(source,atomsByName,dimNames,atomsBase,wantLabel,calculate){this.id=complex_nextId++;var owner;if(source){owner=source.owner;if(!atomsBase){atomsBase=source.atoms}}this.owner=owner||this;this.atoms=atomsBase?Object.create(atomsBase):{};var hadDimNames=!!dimNames;if(!dimNames){dimNames=owner.type._dimsNames}var atomsMap=this.atoms;var D=dimNames.length;var i,dimName;if(atomsByName){var ownerDims=owner._dimensions;var addAtom=function(dimName,value){if(value!=null){var dimension=def.getOwn(ownerDims,dimName);var atom=dimension.intern(value);if(!atomsBase||atom!==atomsBase[dimName]){atomsMap[dimName]=atom}}};if(!hadDimNames){for(dimName in atomsByName){addAtom(dimName,atomsByName[dimName])}}else{for(i=0;igroupLevel){index=i;break}index=i+1}}if(index==null){index=L}}def.array.insertAt(this._dimsList,index,dimension);def.array.insertAt(this._dimsNames,index,name);if(dimension._calculate){index=def.array.binarySearch(this._calcDimsList,dimension._calculationOrder,def.compare,function(dimType){return dimType._calculationOrder});if(index>=0){index++}else{index=~index}def.array.insertAt(this._calcDimsList,index,dimension)}this._isPctRoleDimTypeMap=null;return dimension},addCalculation:function(calcSpec,dimsOptions){calcSpec||def.fail.argumentRequired('calcSpec');var calculation=calcSpec.calculation||def.fail.argumentRequired('calculations[i].calculation');var dimNames=calcSpec.names;if(typeof dimNames==='string'){dimNames=dimNames.split(/\s*\,\s*/)}else{dimNames=def.array.as(dimNames)}if(dimNames&&dimNames.length){var calcDimNames=this._calculatedDimNames;dimNames.forEach(function(name){if(name){name=name.replace(/^\s*(.+?)\s*$/,"$1");!def.hasOwn(calcDimNames,name)||def.fail.argumentInvalid('calculations[i].names',"Dimension name '{0}' is already being calculated.",[name]);var dimType=this._dims[name];if(!dimType){var dimSpec=pvc.data.DimensionType.extendSpec(name,null,dimsOptions);this.addDimension(name,dimSpec)}calcDimNames[name]=true;dimType._toCalculated()}},this)}this._calculations.push(calculation)},isCalculated:function(dimName){return def.hasOwn(this._calculatedDimNames,dimName)},_calculate:function(complex){var calcs=this._calculations;if(calcs.length){var valuesByName={};calcs.forEach(function(calc){calc(complex,valuesByName)});return valuesByName}},getPlayingPercentVisualRoleDimensionMap:function(){var map=this._isPctRoleDimTypeMap;if(!map){map=this._isPctRoleDimTypeMap=new def.Map(def.query(def.own(this._dims)).where(function(dimType){return dimType.playingPercentVisualRole()}).object({name:function(dimType){return dimType.name}}))}return map},sortDimensionNames:function(dims,nameKey){var dimsIndexByName=this._dimsIndexByName;if(!dimsIndexByName){dimsIndexByName=def.query(this._dimsList).object({name:function(dim){return dim.name},value:function(dim,index){return index}});this._dimsIndexByName=dimsIndexByName}dims.sort(function(da,db){return def.compare(dimsIndexByName[nameKey?nameKey(da):da],dimsIndexByName[nameKey?nameKey(db):db])});return dims}});function compType_dimensionRolesChanged(dimType){this._isPctRoleDimTypeMap=null} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/ComplexTypeProject.js b/pacotes/ccc2/compacto/ComplexTypeProject.js deleted file mode 100755 index 80f8c75..0000000 --- a/pacotes/ccc2/compacto/ComplexTypeProject.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.ComplexTypeProject').init(function(dimGroupSpecs){this._dims={};this._dimList=[];this._dimGroupsDims={};this._dimGroupSpecs=dimGroupSpecs||{};this._calcList=[]}).add({_ensureDim:function(name){name||def.fail.argumentInvalid('name',"Invalid dimension name '{0}'.",[name]);var info=def.getOwn(this._dims,name);if(!info){info=this._dims[name]=this._createDim(name);this._dimList.push(info);var groupDimsNames=def.array.lazy(this._dimGroupsDims,info.groupName);def.array.insert(groupDimsNames,name,def.compare)}return info},hasDim:function(name){return def.hasOwn(this._dims,name)},setDim:function(name,spec){var _=this._ensureDim(name).spec;if(spec){def.copy(_,spec)}return this},setDimDefaults:function(name,spec){def.setUDefaults(this._ensureDim(name).spec,spec);return this},_createDim:function(name,spec){var dimGroupName=pvc.data.DimensionType.dimensionGroupName(name);var dimGroupSpec=this._dimGroupSpecs[dimGroupName];if(dimGroupSpec){spec=def.create(dimGroupSpec,spec)}return{name:name,groupName:dimGroupName,spec:spec||{}}},readDim:function(name){var info=this._ensureDim(name);if(info.isRead){throw def.error.operationInvalid("Dimension '{0}' already is the target of a reader.",[name])}if(info.isCalc){throw def.error.operationInvalid("Dimension '{0}' is being calculated, so it cannot be the target of a reader.",[name])}info.isRead=true},calcDim:function(name){var info=this._ensureDim(name);if(info.isCalc){throw def.error.operationInvalid("Dimension '{0}' already is being calculated.",[name])}if(info.isRead){throw def.error.operationInvalid("Dimension '{0}' is the target of a reader, so it cannot be calculated.",[name])}info.isCalc=true},isReadOrCalc:function(name){if(name){var info=def.getOwn(this._dims,name);if(info){return info.isRead||info.isCalc}}return false},groupDimensionsNames:function(groupDimName){return this._dimGroupsDims[groupDimName]},setCalc:function(calcSpec){calcSpec||def.fail.argumentRequired('calculations[i]');calcSpec.calculation||def.fail.argumentRequired('calculations[i].calculation');var dimNames=calcSpec.names;if(typeof dimNames==='string'){dimNames=dimNames.split(/\s*\,\s*/)}else{dimNames=def.array.as(dimNames)}if(dimNames&&dimNames.length){dimNames.forEach(this.calcDim,this)}this._calcList.push(calcSpec)},configureComplexType:function(complexType,translOptions){this._dimList.forEach(function(dimInfo){var dimName=dimInfo.name;var spec=dimInfo.spec;spec=pvc.data.DimensionType.extendSpec(dimName,spec,translOptions);complexType.addDimension(dimName,spec)});this._calcList.forEach(function(calcSpec){complexType.addCalculation(calcSpec)})}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/ComplexView.js b/pacotes/ccc2/compacto/ComplexView.js deleted file mode 100755 index bf3a512..0000000 --- a/pacotes/ccc2/compacto/ComplexView.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.ComplexView',pvc.data.Complex).init(function(source,viewDimNames){this.source=source;this.viewDimNames=viewDimNames;var sourceAtoms=source.atoms,ownSourceAtoms=[];viewDimNames.forEach(function(dimName){if(def.hasOwnProp.call(sourceAtoms,dimName)){ownSourceAtoms[dimName]=sourceAtoms[dimName]}});this.base(source,ownSourceAtoms,viewDimNames,source.owner.atoms,true)}).add({values:function(){return pvc.data.Complex.values(this,this.viewDimNames)},labels:function(){return pvc.data.Complex.labels(this,this.viewDimNames)}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Context.js b/pacotes/ccc2/compacto/Context.js deleted file mode 100755 index 47cc62c..0000000 --- a/pacotes/ccc2/compacto/Context.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.Context').init(function(panel,mark,event){this.chart=panel.chart;this.panel=panel;visualContext_update.call(this,mark,event)}).add({isPinned:false,pin:function(){this.isPinned=true;return this},finished:function(v){return this.sign.finished(v)},delegate:function(dv){return this.sign.delegate(dv)},getV1Series:function(){var s;var series=this.scene.firstAtoms&&(s=this.scene.firstAtoms[this.panel._getV1DimName('series')])&&s.rawValue;if(series==null){series='Series'}return series},getV1Category:function(){var c;return this.scene.firstAtoms&&(c=this.scene.firstAtoms[this.panel._getV1DimName('category')])&&c.rawValue},getV1Value:function(){var v;return this.scene.firstAtoms&&(v=this.scene.firstAtoms[this.panel._getV1DimName('value')])&&v.value},getV1Datum:function(){return this.panel._getV1Datum(this.scene)}});if(Object.defineProperty){try{Object.defineProperty(pvc.visual.Context.prototype,'parent',{get:function(){throw def.error.operationInvalid("The 'this.parent.index' idiom has no equivalent in this version. Please try 'this.pvMark.parent.index'.")}})}catch(ex){}}function visualContext_update(mark,event){this.event=event||null;this.pvMark=mark;var scene;if(mark){var sign=this.sign=mark.sign||null;if(sign){scene=mark.instance().data}if(!scene){this.index=null;scene=new pvc.visual.Scene(null,{panel:this.panel})}else{this.index=scene.childIndex()}}else{this.sign=null;this.index=null;scene=new pvc.visual.Scene(null,{panel:this.panel,group:this.chart.root.data})}this.scene=scene} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/CrosstabTranslationOper.js b/pacotes/ccc2/compacto/CrosstabTranslationOper.js deleted file mode 100755 index 5ccd29f..0000000 --- a/pacotes/ccc2/compacto/CrosstabTranslationOper.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.CrosstabTranslationOper',pvc.data.MatrixTranslationOper).add({virtualItemSize:function(){return this.R+this.C+this.M},_executeCore:function(){if(!this.metadata.length){return def.query()}var dimsReaders=this._getDimensionsReaders();var item=new Array(this.virtualItemSize()),itemCrossGroupIndex=this._itemCrossGroupIndex,me=this;function updateVItemCrossGroup(crossGroupId,source){var itemIndex=itemCrossGroupIndex[crossGroupId],sourceIndex=0,depth=me[crossGroupId];while((depth--)>0){item[itemIndex++]=source[sourceIndex++]}}function updateVItemMeasure(line,cg){var itemIndex=itemCrossGroupIndex.M;var cgIndexes=me._colGroupsIndexes[cg];var depth=me.M;for(var i=0;i0){if(!measuresInColumns){this._colGroups=encodedColGroups;this._colGroupsIndexes=[];this._colGroups.forEach(function(colGroup,cg){this._colGroups[cg]=this._splitEncodedColGroupCell(colGroup);this._colGroupsIndexes[cg]=[this.R+cg]},this);itemCrossGroupTypes.M=[this._columnTypes[this.R]]}else{this.measuresDirection='columns';this._processEncodedColGroups(encodedColGroups)}this.C=this._colGroups[0].length;itemCrossGroupTypes.C=def.array.create(this.C,0)}else{this.C=this.M=0;itemCrossGroupTypes.M=itemCrossGroupTypes.C=[]}}else{this.measuresDirection='rows';this.R=+this.options.measuresIndex;var measuresCount=this.options.measuresCount;if(measuresCount==null){measuresCount=1}this.M=measuresCount;this._colGroups=colNames.slice(this.R+1);this._colGroups.forEach(function(colGroup,cg){this._colGroups[cg]=[colGroup]},this)}}itemCrossGroupTypes.R=this._columnTypes.slice(0,this.R);var seriesInRows=this.options.seriesInRows;var itemGroupIndex=this._itemCrossGroupIndex={'C':!seriesInRows?0:this.R,'R':!seriesInRows?this.C:0,'M':this.C+this.R};var itemTypes=this._itemTypes=new Array(this.virtualItemSize());def.eachOwn(itemGroupIndex,function(groupStartIndex,crossGroup){itemCrossGroupTypes[crossGroup].forEach(function(type,groupIndex){itemTypes[groupStartIndex+groupIndex]=type})});this._itemLogicalGroup={'series':seriesInRows?this.R:this.C,'category':seriesInRows?this.C:this.R,'value':this.M};this._itemLogicalGroupIndex={'series':0,'category':this._itemLogicalGroup.series,'value':this.C+this.R};if(pvc.debug>=3){pvc.log("Crosstab translator "+pvc.stringify({R:this.R,C:this.C,M:this.M}))}},_getCategoriesCount:function(){var R=this.options.categoriesCount;if(R!=null&&(!isFinite(R)||R<0)){R=null}if(R==null){R=def.query(this._columnTypes).whayl(function(type){return type===0}).count();if(!R){R=1}}return R},_splitEncodedColGroupCell:function(colGroup){var values=colGroup.v;var labels;if(values==null){values=[]}else{values=values.split(this._separator);labels=colGroup.f;if(labels){labels=labels.split(this._separator)}}return values.map(function(value,index){return{v:value,f:labels&&labels[index]}})},_processEncodedColGroups:function(encodedColGroups){var L=encodedColGroups.length||def.assert("Must have columns"),R=this.R,colGroups=[],currColGroup,measuresInfo={},measuresInfoList=[];for(var i=0;imeaInfo.groupIndex){meaInfo.groupIndex=currMeaIndex}}measuresInfoList.sort(function(meaInfoA,meaInfoB){return def.compare(meaInfoA.groupIndex,meaInfoB.groupIndex)||def.compare(meaInfoA.index,meaInfoB.index)});var M=measuresInfoList.length;var meaTypes=new Array(M);this._itemCrossGroupTypes.M=meaTypes;measuresInfoList.forEach(function(meaInfoA,index){meaInfoA.groupIndex=index;meaTypes[index]=meaInfoA.type});var CG=colGroups.length,colGroupsValues=new Array(CG),colGroupsIndexes=new Array(CG);colGroups.map(function(colGroup,cg){colGroupsValues[cg]=colGroup.values;var colGroupStartIndex=colGroup.startIndex;var meaIndexes=colGroupsIndexes[cg]=new Array(M);colGroup.measureNames.forEach(function(meaName2,localMeaIndex){var meaIndex=measuresInfo[meaName2].groupIndex;meaIndexes[meaIndex]=R+colGroupStartIndex+localMeaIndex})});this._colGroups=colGroupsValues;this._colGroupsIndexes=colGroupsIndexes;this.M=M},configureType:function(){if(this.measuresDirection==='rows'){throw def.error.notImplemented()}this.base()},_configureTypeCore:function(){var me=this;var itemLogicalGroup=me._itemLogicalGroup;var itemLogicalGroupIndex=me._itemLogicalGroupIndex;var index=0;var dimsReaders=[];function add(dimGroupName,level,count){var crossEndIndex=itemLogicalGroupIndex[dimGroupName]+count;while(count>0){var dimName=pvc.buildIndexedId(dimGroupName,level);if(!me.complexTypeProj.isReadOrCalc(dimName)){index=me._nextAvailableItemIndex(index);if(index>=crossEndIndex){return}dimsReaders.push({names:dimName,indexes:index});index++;count--}level++}}var dataPartDimName=this.options.dataPartDimName;if(dataPartDimName&&this.C===1&&!this.complexTypeProj.isReadOrCalc(dataPartDimName)){var plot2SeriesIndexes=this.options.plot2SeriesIndexes;if(plot2SeriesIndexes!=null){var seriesKeys=this._colGroups.map(function(colGroup){return''+colGroup[0].v});this._plot2SeriesKeySet=this._createPlot2SeriesKeySet(plot2SeriesIndexes,seriesKeys)}}['series','category','value'].forEach(function(dimGroupName){var L=itemLogicalGroup[dimGroupName];if(L>0){add(dimGroupName,0,L)}});if(dimsReaders){dimsReaders.forEach(this.defReader,this)}if(this._plot2SeriesKeySet){var seriesReader=this._userDimsReadersByDim.series;if(seriesReader){var calcAxis2SeriesKeySet=def.fun.constant(this._plot2SeriesKeySet);this._userRead(this._dataPartGet(calcAxis2SeriesKeySet,seriesReader),dataPartDimName)}}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Data.compat.js b/pacotes/ccc2/compacto/Data.compat.js deleted file mode 100755 index 17523e4..0000000 --- a/pacotes/ccc2/compacto/Data.compat.js +++ /dev/null @@ -1 +0,0 @@ -pvc.data.Data.add({getInfo:function(){var out=["DATA SUMMARY",pvc.logSeparator," Dimension",pvc.logSeparator];def.eachOwn(this.dimensions(),function(dimension,name){var count=dimension.count(),type=dimension.type,features=[];features.push('"'+type.label+'"');features.push(type.valueTypeName);if(type.isComparable){features.push("comparable")}if(!type.isDiscrete){features.push("continuous")}if(type.isHidden){features.push("hidden")}out.push(" "+name+" ("+features.join(', ')+")"+" ("+count+")\n\t"+dimension.atoms().slice(0,10).map(function(atom){return atom.label}).join(", ")+(count>10?"...":""))});return out.join("\n")},getValues:function(){return pv.range(0,this.getCategoriesSize()).map(function(categIndex){return this._getValuesForCategoryIndex(categIndex)},this)},_getDimensionValues:function(name){return this.dimensions(name).atoms().map(function(atom){return atom.value})},_getDimensionVisibleValues:function(name){return this.dimensions(name).atoms({visible:true}).map(function(atom){return atom.value})},getSeries:function(){return this._getDimensionValues('series')},getVisibleSeriesIndexes:function(){return this.dimensions('series').indexes({visible:true})},getVisibleCategoriesIndexes:function(){return this.dimensions('category').indexes({visible:true})},getVisibleSeries:function(){return this._getDimensionVisibleValues('series')},getCategories:function(){return this._getDimensionValues('category')},getVisibleCategories:function(){return this._getDimensionVisibleValues('category')},_getValuesForCategoryIndex:function(categIdx){var categAtom=this.dimensions('category').atoms()[categIdx];var datumsBySeriesKey=this.datums({category:categAtom}).uniqueIndex(function(datum){return datum.atoms.series.key});return this.dimensions('series').atoms().map(function(atom){var datum=def.getOwn(datumsBySeriesKey,atom.key);return datum?datum.atoms.value.value:null})},getSeriesSize:function(){var dim=this.dimensions('series',{assertExists:false});return dim?dim.count():0},getCategoriesSize:function(){var dim=this.dimensions('category',{assertExists:false});return dim?dim.count():0}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Data.js b/pacotes/ccc2/compacto/Data.js deleted file mode 100755 index c53b0e6..0000000 --- a/pacotes/ccc2/compacto/Data.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.Data',pvc.data.Complex).init(function(keyArgs){keyArgs||def.fail.argumentRequired('keyArgs');this._visibleDatums=new def.Map();var owner,atoms,atomsBase,dimNames,datums,index,parent=this.parent=keyArgs.parent||null;if(parent){this.root=parent.root;this.depth=parent.depth+1;this.type=parent.type;datums=keyArgs.datums||def.fail.argumentRequired('datums');owner=parent.owner;atoms=keyArgs.atoms||def.fail.argumentRequired('atoms');dimNames=keyArgs.dimNames||def.fail.argumentRequired('dimNames');atomsBase=parent.atoms}else{this.root=this;dimNames=[];var linkParent=keyArgs.linkParent||null;if(linkParent){owner=linkParent.owner;this.type=owner.type;datums=keyArgs.datums||def.fail.argumentRequired('datums');this._leafs=[];atomsBase=linkParent.atoms;index=def.get(keyArgs,'index',null);data_addLinkChild.call(linkParent,this,index)}else{owner=this;atomsBase={};if(keyArgs.labelSep){this.labelSep=keyArgs.labelSep}this.type=keyArgs.type||def.fail.argumentRequired('type');this._selectedDatums=new def.Map()}}if(datums){data_setDatums.call(this,datums)}this.owner=owner;this._atomsBase=atomsBase;this._dimensions={};this.type.dimensionsList().forEach(this._initDimension,this);this.base(owner,atoms,dimNames,atomsBase,true);pv.Dom.Node.call(this,null);delete this.nodeValue;this._children=this.childNodes;if(parent){index=def.get(keyArgs,'index',null);data_addChild.call(parent,this,index);if(parent.absLabel){this.absLabel=def.string.join(owner.labelSep,parent.absLabel,this.label)}else{this.absLabel=this.label}if(parent.absKey){this.absKey=def.string.join(",",parent.absKey,this.key)}else{this.absKey=this.key}}else{this.absLabel=this.label;this.absKey=this.key}}).add(pv.Dom.Node).add({parent:null,linkParent:null,_dimensions:null,_freeDimensionNames:null,_children:null,_linkChildren:null,_leafs:null,_childrenByKey:null,_visibleDatums:null,_selectedDatums:null,_groupByCache:null,_sumAbsCache:null,treeHeight:null,_groupOper:null,_groupSpec:null,_groupLevel:null,_datums:null,_datumsById:null,depth:0,label:"",absLabel:"",_disposed:false,_isFlattenGroup:false,_isDegenerateFlattenGroup:false,_initDimension:function(dimType){this._dimensions[dimType.name]=new pvc.data.Dimension(this,dimType)},dimensions:function(name,keyArgs){if(name==null){return this._dimensions}var dim=def.getOwn(this._dimensions,name);if(!dim&&def.get(keyArgs,'assertExists',true)){throw def.error.argumentInvalid('name',"Undefined dimension '{0}'.",[name])}return dim},freeDimensionNames:function(){if(!this._freeDimensionNames){var free=this._freeDimensionNames=[];def.eachOwn(this._dimensions,function(dim,dimName){var atom=this.atoms[dimName];if(!(atom instanceof pvc.data.Atom)||atom.value==null){free.push(dimName)}},this)}return this._freeDimensionNames},isOwner:function(){return this.owner===this},children:function(){if(!this._children){return def.query()}return def.query(this._children)},childCount:function(){return this._children?this._children.length:0},leafs:function(){return def.query(this._leafs)},count:function(){return this._datums.length},singleDatum:function(){var datums=this._datums;return datums.length===1?datums[0]:null},dispose:function(){if(!this._disposed){data_disposeChildLists.call(this);if(this._selectedDatums){this._selectedDatums.clear()}this._visibleDatums.clear();def.eachOwn(this._dimensions,function(dimension){dimension.dispose()});if(this.parent){this.parent.removeChild(this);this.parent=null}if(this.linkParent){data_removeLinkChild.call(this.linkParent,this)}this._disposed=true}},disposeChildren:function(){data_disposeChildLists.call(this)}});function data_addChild(child,index){this.insertAt(child,index);(this._childrenByKey||(this._childrenByKey={}))[child.key]=child}function data_addLinkChild(linkChild,index){data_addColChild(this,'_linkChildren',linkChild,'linkParent',index)}function data_removeLinkChild(linkChild){data_removeColChild(this,'_linkChildren',linkChild,'linkParent')}function data_disposeChildLists(){data_disposeChildList(this._children,'parent');this._childrenByKey=null;data_disposeChildList(this._linkChildren,'linkParent');this._groupByCache=null;this._sumAbsCache=null}function data_assertIsOwner(){this.isOwner()||def.fail("Can only be called on the owner data.")} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Data.operations.js b/pacotes/ccc2/compacto/Data.operations.js deleted file mode 100755 index 778e21f..0000000 --- a/pacotes/ccc2/compacto/Data.operations.js +++ /dev/null @@ -1 +0,0 @@ -pvc.data.Data.add({load:function(atomz,keyArgs){data_assertIsOwner.call(this);var whereFun=def.get(keyArgs,'where');var isNullFun=def.get(keyArgs,'isNull');var datums=def.query(atomz).select(function(atoms){var datum=new pvc.data.Datum(this,atoms);if(isNullFun&&isNullFun(datum)){datum.isNull=true}if(whereFun&&!whereFun(datum)){return null}return datum},this);data_setDatums.call(this,datums,{doAtomGC:true})},clearVirtuals:function(){var datums=this._datums;if(datums){this._sumAbsCache=null;var visibleDatums=this._visibleDatums;var selectedDatums=this._selectedDatums;var i=0;var L=datums.length;var removed;while(i=7){pvc.log("[GroupBy] "+(cacheKey?("Cache key not found: '"+cacheKey+"'"):"No Cache key"))}data=groupOper.execute();if(cacheKey){(groupByCache||(this._groupByCache={}))[cacheKey]=data}}else if(pvc.debug>=7){pvc.log("[GroupBy] Cache key hit '"+cacheKey+"'")}return data},flattenBy:function(role,keyArgs){var grouping=role.flattenedGrouping(keyArgs)||def.fail.operationInvalid("Role is unbound.");return this.groupBy(grouping,keyArgs)},where:function(whereSpec,keyArgs){var datums=this.datums(whereSpec,keyArgs);return new pvc.data.Data({linkParent:this,datums:datums})},datums:function(whereSpec,keyArgs){if(!whereSpec){if(!keyArgs){return def.query(this._datums)}return data_whereState(def.query(this._datums),keyArgs)}whereSpec=data_processWhereSpec.call(this,whereSpec,keyArgs);return data_where.call(this,whereSpec,keyArgs)},datum:function(whereSpec,keyArgs){whereSpec||def.fail.argumentRequired('whereSpec');whereSpec=data_processWhereSpec.call(this,whereSpec,keyArgs);var datum=data_where.call(this,whereSpec,keyArgs).first()||null;if(!datum&&def.get(keyArgs,'createNull')&&whereSpec.length){var sourceDatumFilter=whereSpec[0],atoms={};for(var dimName in this._dimensions){var dimAtoms=sourceDatumFilter[dimName];if(dimAtoms){atoms[dimName]=dimAtoms[0]}}datum=new pvc.data.Datum(this,atoms,true)}return datum},firstDatum:function(){return this._datums.length?this._datums[0]:null},dimensionsSumAbs:function(dimName,keyArgs){var key=dimName+":"+dim_buildDatumsFilterKey(keyArgs),sum=def.getOwn(this._sumAbsCache,key);if(sum==null){sum=this.children().where(function(childData){return!childData._isFlattenGroup||childData._isDegenerateFlattenGroup}).select(function(childData){return Math.abs(childData.dimensions(dimName).sum(keyArgs))},this).reduce(def.add,0);(this._sumAbsCache||(this._sumAbsCache={}))[key]=sum}return sum}});function data_setDatums(newDatums,keyArgs){newDatums||def.fail.argumentRequired('newDatums');var doAtomGC=def.get(keyArgs,'doAtomGC',false);var isAdditive=def.get(keyArgs,'isAdditive',false);var visibleDatums=this._visibleDatums;var selectedDatums=this._selectedDatums;var newDatumsByKey={};var prevDatumsByKey;var prevDatums=this._datums;if(prevDatums){var processPrevAtoms=isAdditive&&doAtomGC;prevDatumsByKey=def.query(prevDatums).uniqueIndex(function(datum){if(processPrevAtoms){data_processDatumAtoms.call(this,datum,false,true)}return datum.key},this);if(isAdditive){this._sumAbsCache=null}else{data_disposeChildLists.call(this);if(selectedDatums){selectedDatums.clear()}visibleDatums.clear()}}else{isAdditive=false}var datumsById;if(isAdditive){datumsById=this._datumsById}else{datumsById=this._datumsById={}}if(def.array.is(newDatums)){var i=0;var L=newDatums.length;while(i=0){throw def.error.argumentInvalid('keyArgs.orderBy',"Multi-dimension order by is not supported.")}}var rootData=this.groupBy(groupingSpecText,keyArgs),H=rootData.treeHeight;var stateStack=[];return def.query(function(){var state;if(!this._data){this._data=rootData;this._dimAtomsOrQuery=def.query(datumFilter[rootData._groupLevelSpec.dimensions[0].name])}else if(this._datumsQuery){this._data||def.assert("Must have a current data");stateStack.length||def.assert("Must have a parent data");!this._dimAtomsOrQuery||def.assert();if(this._datumsQuery.next()){this.item=this._datumsQuery.item;return 1}this._datumsQuery=null;state=stateStack.pop();this._data=state.data;this._dimAtomsOrQuery=state.dimAtomsOrQuery}this._dimAtomsOrQuery||def.assert("Invalid programmer");this._data||def.assert("Must have a current data");var depth=stateStack.length;do{while(this._dimAtomsOrQuery.next()){var dimAtomOr=this._dimAtomsOrQuery.item,childData=this._data._childrenByKey[dimAtomOr.key];if(childData&&(depth0},atoms:function(keyArgs){if(this._lazyInit){this._lazyInit()}var visible=def.get(keyArgs,'visible');if(visible==null){return this._atoms}visible=!!visible;this._visibleAtoms||(this._visibleAtoms={});return this._visibleAtoms[visible]||(this._visibleAtoms[visible]=dim_calcVisibleAtoms.call(this,visible))},indexes:function(keyArgs){if(this._lazyInit){this._lazyInit()}var visible=def.get(keyArgs,'visible');if(visible==null){return pv.range(0,this._atoms.length)}visible=!!visible;this._visibleIndexes||(this._visibleIndexes={});return this._visibleIndexes[visible]||(this._visibleIndexes[visible]=dim_calcVisibleIndexes.call(this,visible))},atom:function(value){if(value==null||value===''){return this._nullAtom}if(value instanceof pvc.data.Atom){return value}if(this._lazyInit){this._lazyInit()}var key=this.type._key?this.type._key.call(null,value):value;return this._atomsByKey[key]||null},extent:function(keyArgs){var atoms=this.atoms(keyArgs);var L=atoms.length;if(!L){return undefined}var offset=this._nullAtom&&atoms[0].value==null?1:0;var countWithoutNull=L-offset;if(countWithoutNull>0){var min=atoms[offset];var max=atoms[L-1];var tmp;if(min!==max&&def.get(keyArgs,'abs',false)){var minSign=min.value<0?-1:1;var maxSign=max.value<0?-1:1;if(minSign===maxSign){if(maxSign<0){tmp=max;max=min;min=tmp}}else if(countWithoutNull>2){if(max.value<-min.value){max=min}var zeroIndex=def.array.binarySearch(atoms,0,this.type.comparer(),function(a){return a.value});if(zeroIndex<0){zeroIndex=~zeroIndex;var negAtom=atoms[zeroIndex-1];var posAtom=atoms[zeroIndex];if(-negAtom.valueoffset)?atoms[offset]:undefined},max:function(keyArgs){var atoms=this.atoms(keyArgs);var L=atoms.length;return L&&atoms[L-1].value!=null?atoms[L-1]:undefined},sum:function(keyArgs){var isAbs=!!def.get(keyArgs,'abs',false),zeroIfNone=def.get(keyArgs,'zeroIfNone',true),key=dim_buildDatumsFilterKey(keyArgs)+':'+isAbs;var sum=def.getOwn(this._sumCache,key);if(sum===undefined){var dimName=this.name;sum=this.data.datums(null,keyArgs).reduce(function(sum2,datum){var value=datum.atoms[dimName].value;if(isAbs&&value<0){value=-value}return sum2!=null?(sum2+value):value},null);(this._sumCache||(this._sumCache={}))[key]=sum}return zeroIfNone?(sum||0):sum},percent:function(atomOrValue,keyArgs){var value=(atomOrValue instanceof pvc.data.Atom)?atomOrValue.value:atomOrValue;if(!value){return 0}var sum=this.sum(def.create(keyArgs,{abs:true}));return sum?(Math.abs(value)/sum):0},percentOverParent:function(keyArgs){var value=this.sum(keyArgs);if(!value){return 0}var parentData=this.data.parent;if(!parentData){return 0}var sum=parentData.dimensionsSumAbs(this.name,keyArgs);return sum?(Math.abs(value)/sum):0},format:function(value,sourceValue){return""+(this.type._formatter?this.type._formatter.call(null,value,sourceValue):"")},intern:function(sourceValue,isVirtual){if(sourceValue==null||sourceValue===''){return this._nullAtom||dim_createNullAtom.call(this,sourceValue)}if(sourceValue instanceof pvc.data.Atom){if(sourceValue.dimension!==this){throw def.error.operationInvalid("Atom is of a different dimension.")}return sourceValue}var value,label;var type=this.type;if(typeof sourceValue==='object'&&('v'in sourceValue)){label=sourceValue.f;sourceValue=sourceValue.v}if(!isVirtual){var converter=type._converter;value=converter?converter(sourceValue):sourceValue;if(value==null||value===''){return this._nullAtom||dim_createNullAtom.call(this,sourceValue)}}else{value=sourceValue}var cast=type.cast;if(cast){value=cast(value);if(value==null||value===''){return this._nullAtom||dim_createNullAtom.call(this)}}var keyFun=type._key;var key=''+(keyFun?keyFun(value):value);key||def.fail.operationInvalid("Only a null value can have an empty key.");var atom=this._atomsByKey[key];if(atom){if(!isVirtual&&atom.isVirtual){delete atom.isVirtual}return atom}return dim_createAtom.call(this,type,sourceValue,key,value,label,isVirtual)},dispose:function(){if(!this._disposed){data_disposeChildList(this._children,'parent');data_disposeChildList(this._linkChildren,'linkParent');if(this.parent){dim_removeChild.call(this.parent,this)}if(this.linkParent){dim_removeLinkChild.call(this.linkParent,this)}dim_clearVisiblesCache.call(this);this._lazyInit=null;this._atoms=this._nullAtom=this._virtualNullAtom=null;this._disposed=true}}});function dim_createAtom(type,sourceValue,key,value,label,isVirtual){var atom;if(this.owner===this){if(label==null){var formatter=type._formatter;if(formatter){label=formatter(value,sourceValue)}else{label=value}}label=""+label;if(!label&&pvc.debug>=2){pvc.log("Only the null value should have an empty label.")}atom=new pvc.data.Atom(this,value,label,sourceValue,key);if(isVirtual){atom.isVirtual=true}}else{var source=this.parent||this.linkParent;atom=source._atomsByKey[key]||dim_createAtom.call(source,type,sourceValue,key,value,label,isVirtual)}def.array.insert(this._atoms,atom,this._atomComparer);dim_clearVisiblesCache.call(this);this._atomsByKey[key]=atom;return atom}function dim_internAtom(atom){var key=atom.key;if(atom.dimension===this){(this.owner===this)||def.assert("Should be an owner dimension");if(!key&&atom===this._virtualNullAtom){atom=this.intern(null)}return atom}if(!this._lazyInit){var localAtom=this._atomsByKey[key];if(localAtom){if(localAtom!==atom){throw def.error.operationInvalid("Atom is from a different root data.")}return atom}if(this.owner===this){throw def.error.operationInvalid("Atom is from a different root data.")}}dim_internAtom.call(this.parent||this.linkParent,atom);if(!this._lazyInit){this._atomsByKey[key]=atom;if(!key){this._nullAtom=atom;this._atoms.unshift(atom)}else{def.array.insert(this._atoms,atom,this._atomComparer)}dim_clearVisiblesCache.call(this)}return atom}function dim_buildDatumsFilterKey(keyArgs){var visible=def.get(keyArgs,'visible'),selected=def.get(keyArgs,'selected');return(visible==null?null:!!visible)+':'+(selected==null?null:!!selected)}function dim_createNullAtom(sourceValue){var nullAtom=this._nullAtom;if(!nullAtom){if(this.owner===this){var typeFormatter=this.type._formatter;var label=""+(typeFormatter?typeFormatter.call(null,null,sourceValue):"");nullAtom=new pvc.data.Atom(this,null,label,null,'');this.data._atomsBase[this.name]=nullAtom}else{nullAtom=dim_createNullAtom.call(this.parent||this.linkParent,sourceValue)}this._atomsByKey['']=this._nullAtom=nullAtom;this._atoms.unshift(nullAtom)}return nullAtom}function dim_createVirtualNullAtom(){(this.owner===this)||def.assert("Can only create atoms on an owner dimension.");if(!this._virtualNullAtom){this._virtualNullAtom=new pvc.data.Atom(this,null,"",null,'');this.data._atomsBase[this.name]=this._virtualNullAtom}return this._virtualNullAtom}function dim_unintern(atom){(this.owner===this)||def.assert("Can only unintern atoms on an owner dimension.");(atom&&atom.dimension===this)||def.assert("Not an interned atom");if(atom===this._virtualNullAtom){return}var key=atom.key;if(this._atomsByKey[key]===atom){def.array.remove(this._atoms,atom,this._atomComparer);delete this._atomsByKey[key];if(!key){delete this._nullAtom;this.data._atomsBase[this.name]=this._virtualNullAtom}}dim_clearVisiblesCache.call(this)}function dim_uninternUnvisitedAtoms(){(this.owner===this)||def.assert("Can only unintern atoms of an owner dimension.");var atoms=this._atoms;if(atoms){var atomsByKey=this._atomsByKey;var i=0;var L=atoms.length;while(i0))||def.assert("Must have had accounted for at least one visible datum.");map[key]=(count||0)+(visible?1:-1);this._visibleAtoms=this._sumCache=this._visibleIndexes=null}}function dim_getVisibleDatumsCountMap(){var map=this._atomVisibleDatumsCount;if(!map){map={};this.data.datums(null,{visible:true}).each(function(datum){var atom=datum.atoms[this.name],key=atom.key;map[key]=(map[key]||0)+1},this);this._atomVisibleDatumsCount=map}return map}function dim_calcVisibleIndexes(visible){var indexes=[];this._atoms.forEach(function(atom,index){if(this.isVisible(atom)===visible){indexes.push(index)}},this);return indexes}function dim_calcVisibleAtoms(visible){return def.query(this._atoms).where(function(atom){return this.isVisible(atom)===visible},this).array()} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/DimensionType.js b/pacotes/ccc2/compacto/DimensionType.js deleted file mode 100755 index 3e2d7ff..0000000 --- a/pacotes/ccc2/compacto/DimensionType.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.DimensionType').init(function(complexType,name,keyArgs){this.complexType=complexType;this.name=name;this.label=def.get(keyArgs,'label')||pvc.buildTitleFromName(name);var groupAndLevel=pvc.splitIndexedId(name);this.group=groupAndLevel[0];this.groupLevel=def.nullyTo(groupAndLevel[1],0);if(this.label.indexOf('{')>=0){this.label=def.format(this.label,[this.groupLevel+1])}this.playedVisualRoles=new def.Map();this.isHidden=!!def.get(keyArgs,'isHidden');var valueType=def.get(keyArgs,'valueType')||null;var valueTypeName=pvc.data.DimensionType.valueTypeName(valueType);var cast=def.getOwn(pvc.data.DimensionType.cast,valueTypeName,null);this.valueType=valueType;this.valueTypeName=valueTypeName;this.cast=cast;this.isDiscreteValueType=(this.valueType!==Number&&this.valueType!==Date);this.isDiscrete=def.get(keyArgs,'isDiscrete');if(this.isDiscrete==null){this.isDiscrete=this.isDiscreteValueType}else{this.isDiscrete=!!this.isDiscrete;if(!this.isDiscrete&&this.isDiscreteValueType){throw def.error.argumentInvalid('isDiscrete',"The only supported continuous value types are Number and Date.")}}this._converter=def.get(keyArgs,'converter')||null;if(!this._converter){var rawFormat=def.get(keyArgs,'rawFormat');if(rawFormat){switch(this.valueType){case Date:this._converter=pv.Format.createParser(pv.Format.date(rawFormat));break}}}this._key=def.get(keyArgs,'key')||null;this._comparer=def.get(keyArgs,'comparer');if(this._comparer===undefined){switch(this.valueType){case Number:case Date:this._comparer=def.compare;break;default:this._comparer=null}}this.isComparable=this._comparer!=null;this._formatter=def.get(keyArgs,'formatter')||null;if(!this._formatter){switch(this.valueType){case Number:this._formatter=pv.Format.createFormatter(pv.Format.number().fractionDigits(0,2));break;case Date:var format=def.get(keyArgs,'format');if(!format){format=def.get(keyArgs,'rawFormat');if(format){format=format.replace(/-/g,"/")}}if(!format){format="%Y/%m/%d"}this._formatter=pv.Format.createFormatter(pv.Format.date(format));break}}}).add({isCalculated:false,compare:function(a,b){if(a==null){if(b==null){return 0}return-1}else if(b==null){return 1}return this._comparer.call(null,a,b)},comparer:function(reverse){if(!this.isComparable){return null}var me=this;if(reverse){return this._reverseComparer||(this._reverseComparer=function(a,b){return me.compare(b,a)})}return this._directComparer||(this._directComparer=function(a,b){return me.compare(a,b)})},atomComparer:function(reverse){if(reverse){return this._reverseAtomComparer||(this._reverseAtomComparer=this._createReverseAtomComparer())}return this._directAtomComparer||(this._directAtomComparer=this._createDirectAtomComparer())},_toDiscrete:function(){this.isDiscrete=true},_toCalculated:function(){this.isCalculated=true},_createReverseAtomComparer:function(){if(!this.isComparable){return atom_idComparerReverse}var me=this;function reverseAtomComparer(a,b){if(a===b){return 0}return me.compare(b.value,a.value)}return reverseAtomComparer},_createDirectAtomComparer:function(){if(!this.isComparable){return atom_idComparer}var me=this;function directAtomComparer(a,b){if(a===b){return 0}return me.compare(a.value,b.value)}return directAtomComparer},formatter:function(){return this._formatter},converter:function(){return this._converter},playingPercentVisualRole:function(){return def.query(this.playedVisualRoles.values()).any(function(visualRole){return visualRole.isPercent})}});pvc.data.DimensionType.cast={'Date':function(value){return value instanceof Date?value:new Date(value)},'Number':function(value){value=Number(value);return isNaN(value)?null:value},'String':String,'Boolean':Boolean,'Object':Object,'Any':null};pvc.data.DimensionType.dimensionGroupName=function(dimName){return dimName.replace(/^(.*?)(\d*)$/,"$1")};pvc.data.DimensionType.valueTypeName=function(valueType){if(valueType==null){return"Any"}switch(valueType){case Boolean:return'Boolean';case Number:return'Number';case String:return'String';case Object:return'Object';case Date:return'Date';default:throw def.error.argumentInvalid('valueType',"Invalid valueType function: '{0}'.",[valueType])}};pvc.data.DimensionType.extendSpec=function(dimName,dimSpec,keyArgs){var dimGroup=pvc.data.DimensionType.dimensionGroupName(dimName),userDimGroupsSpec=def.get(keyArgs,'dimensionGroups');if(userDimGroupsSpec){var groupDimSpec=userDimGroupsSpec[dimGroup];if(groupDimSpec){dimSpec=def.create(groupDimSpec,dimSpec)}}if(!dimSpec){dimSpec={}}switch(dimGroup){case'category':var isCategoryTimeSeries=def.get(keyArgs,'isCategoryTimeSeries',false);if(isCategoryTimeSeries){if(dimSpec.valueType===undefined){dimSpec.valueType=Date}}break;case'value':if(dimSpec.valueType===undefined){dimSpec.valueType=Number}if(dimSpec.valueType===Number){if(dimSpec.formatter===undefined&&!dimSpec.format){dimSpec.formatter=def.get(keyArgs,'valueNumberFormatter')}}break}if(dimSpec.converter===undefined&&dimSpec.valueType===Date&&!dimSpec.rawFormat){dimSpec.rawFormat=def.get(keyArgs,'timeSeriesFormat')}return dimSpec};function dimType_addVisualRole(visualRole){this.playedVisualRoles.set(visualRole.name,visualRole);compType_dimensionRolesChanged.call(this.type,this)}function dimType_removeVisualRole(visualRole){this.playedVisualRoles.rem(visualRole.name);compType_dimensionRolesChanged.call(this.type,this)} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Dot.js b/pacotes/ccc2/compacto/Dot.js deleted file mode 100755 index a666814..0000000 --- a/pacotes/ccc2/compacto/Dot.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.Dot',pvc.visual.Sign).init(function(panel,parentMark,keyArgs){var pvMark=parentMark.add(pv.Dot);var protoMark=def.get(keyArgs,'proto');if(protoMark){pvMark.extend(protoMark)}keyArgs=def.setDefaults(keyArgs,'freeColor',false);this.base(panel,pvMark,keyArgs);if(!def.get(keyArgs,'freePosition',false)){var basePosProp=panel.isOrientationVertical()?"left":"bottom",orthoPosProp=panel.anchorOrtho(basePosProp);this._lockDynamic(orthoPosProp,'y')._lockDynamic(basePosProp,'x')}this._bindProperty('shape','shape')._bindProperty('shapeRadius','radius')._bindProperty('shapeSize','size').optional('strokeDasharray',undefined).optional('lineWidth',1.5)}).prototype.property('size').constructor.add({y:function(){return 0},x:function(){return 0},shape:function(){return this.delegateExtension()},radius:function(){this.state.radius=this.delegateExtension()},baseSize:function(){var radius=this.state.radius;if(radius!=null){return radius*radius}return this.base()},defaultSize:function(){return 12},interactiveSize:function(size){if(this.scene.isActive){return Math.max(size,5)*2.5}return size},interactiveColor:function(color,type){var scene=this.scene;if(scene.isActive){if(type==='stroke'){return color.brighter(1)}}else if(this.showsSelection()&&scene.anySelected()&&!scene.isSelected()){if(this.isActiveSeriesAware&&scene.isActiveSeries()){return color.alpha(0.8)}else{switch(type){case'fill':return this.dimColor(color,type);case'stroke':return color.alpha(0.45)}}}return this.base(color,type)}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/GroupingOper.js b/pacotes/ccc2/compacto/GroupingOper.js deleted file mode 100755 index fba406e..0000000 --- a/pacotes/ccc2/compacto/GroupingOper.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.GroupingOper',pvc.data.DataOper).init(function(linkParent,groupingSpecs,keyArgs){groupingSpecs||def.fail.argumentRequired('groupingSpecs');this.base(linkParent,keyArgs);this._where=def.get(keyArgs,'where');this._visible=def.get(keyArgs,'visible',null);this._selected=def.get(keyArgs,'selected',null);this._isNull=def.get(keyArgs,'isNull',null);var hasKey=this._selected==null,whereKey='';if(this._where){whereKey=def.get(keyArgs,'whereKey');if(!whereKey){if(!keyArgs||whereKey===null){hasKey=false}else{whereKey=''+def.nextId('dataOperWhereKey');keyArgs.whereKey=whereKey}}}var ids=[];this._groupSpecs=def.array.as(groupingSpecs).map(function(groupSpec){if(groupSpec instanceof pvc.data.GroupingSpec){if(groupSpec.type!==linkParent.type){throw def.error.argumentInvalid('groupingSpecText',"Invalid associated complex type.")}}else{groupSpec=pvc.data.GroupingSpec.parse(groupSpec,linkParent.type)}ids.push(groupSpec.id);return groupSpec});if(hasKey){this.key=ids.join('!!')+"||visible:"+this._visible+"||isNull:"+this._isNull+"||where:"+whereKey}}).add({execute:function(){var datumsQuery=data_whereState(def.query(this._linkParent._datums),{visible:this._visible,selected:this._selected,isNull:this._isNull,where:this._where});var rootNode=this._group(datumsQuery);return this._generateData(rootNode,null,this._linkParent)},executeAdd:function(rootData,datums){var datumsQuery=data_whereState(def.query(datums),{visible:this._visible,selected:this._selected,isNull:this._isNull,where:this._where});var rootNode=this._group(datumsQuery);this._generateData(rootNode,null,this._linkParent,rootData);return rootNode.datums},_group:function(datumsQuery){var rootNode={isRoot:true,treeHeight:def.query(this._groupSpecs).select(function(spec){var levelCount=spec.levels.length;if(!levelCount){return 0}return!!spec.flatteningMode?1:levelCount}).reduce(def.add,0),datums:[]};if(rootNode.treeHeight>0){this._groupSpecRecursive(rootNode,datumsQuery,0)}return rootNode},_groupSpecRecursive:function(specParentNode,specDatumsQuery,specIndex){var groupSpec=this._groupSpecs[specIndex];var levelSpecs=groupSpec.levels;var L=levelSpecs.length;var doFlatten=!!groupSpec.flatteningMode;var nextSpecIndex=specIndex+1;var isLastSpec=(nextSpecIndex>=this._groupSpecs.length);var isPostOrder=doFlatten&&(groupSpec.flatteningMode==='tree-post');var specGroupParent;if(doFlatten){specParentNode.children=[];specParentNode.childrenByKey={};specGroupParent={key:'',absKey:'',atoms:{},datums:[],label:groupSpec.flattenRootLabel,dimNames:[]};if(!isPostOrder){specParentNode.children.push(specGroupParent);specParentNode.childrenByKey['']=specGroupParent}}else{specGroupParent=specParentNode}groupLevelRecursive.call(this,specGroupParent,specDatumsQuery,0);if(doFlatten){if(isPostOrder){specParentNode.children.push(specGroupParent)}specParentNode.datums=specGroupParent.datums}function groupLevelRecursive(levelParentNode,levelDatums,levelIndex){var levelSpec=levelSpecs[levelIndex];if(!doFlatten){levelParentNode.children=[];levelParentNode.groupSpec=groupSpec;levelParentNode.groupLevelSpec=levelSpec}var childNodes=this._groupDatums(levelSpec,levelParentNode,levelDatums,doFlatten);var isLastSpecLevel=levelIndex===L-1;var willRecurseParent=doFlatten&&!isLastSpec;var levelParentDatums=willRecurseParent?[]:levelParentNode.datums;childNodes.forEach(function(child){var childDatums=child.datums;if(!(isLastSpec&&isLastSpecLevel)){child.datums=[]}var specParentChildIndex;if(!doFlatten){levelParentNode.children.push(child)}else{def.array.lazy(levelParentNode,'_children').push(child);if(def.hasOwn(specParentNode.childrenByKey,child.key)){def.array.append(levelParentDatums,childDatums);return}specParentChildIndex=specParentNode.children.length;if(!isPostOrder){specParentNode.children.push(child);specParentNode.childrenByKey[child.key]=child;levelParentNode.isFlattenGroup=true}}if(!isLastSpecLevel){groupLevelRecursive.call(this,child,childDatums,levelIndex+1)}else if(!isLastSpec){this._groupSpecRecursive(child,childDatums,nextSpecIndex)}def.array.append(levelParentDatums,child.datums);if(doFlatten&&isPostOrder){if(def.hasOwn(specParentNode.childrenByKey,child.key)){child.isFlattenGroup||def.assert("Must be a parent for duplicate keys to exist.");if(child._children.length===1){specParentNode.children.splice(specParentChildIndex,specParentNode.children.length-specParentChildIndex);child.isDegenerateFlattenGroup=true}}specParentNode.children.push(child);specParentNode.childrenByKey[child.key]=child;levelParentNode.isFlattenGroup=true}},this);if(willRecurseParent){this._groupSpecRecursive(levelParentNode,levelParentDatums,nextSpecIndex)}}},_groupDatums:function(levelSpec,levelParentNode,levelDatums,doFlatten){var firstDatums=[];var childNodes=new def.OrderedMap();def.query(levelDatums).each(function(datum){var newChild=levelSpec.key(datum);var key=newChild.key;var child=childNodes.get(key);if(child){child.datums.push(datum)}else{child=newChild;child.datums=[datum];if(doFlatten){def.copy(child.atoms,levelParentNode.atoms);if(levelParentNode.dimNames.length){var keySep=datum.owner.keySep;child.absKey=levelParentNode.absKey+keySep+key;var K=keySep.length;var trimKey=child.absKey;while(trimKey.lastIndexOf(keySep)===trimKey.length-K){trimKey=trimKey.substr(0,trimKey.length-K)}child.key=trimKey}else{child.absKey=key}child.dimNames=levelSpec.accDimensionNames()}var datumIndex=def.array.insert(firstDatums,datum,levelSpec.comparer);childNodes.add(key,child,~datumIndex)}});return childNodes},_generateData:function(node,parentNode,parentData,rootData){var data,isNew;if(node.isRoot){if(rootData){data=rootData;data_addDatumsLocal.call(data,node.datums)}else{isNew=true;data=new pvc.data.Data({linkParent:parentData,datums:node.datums});data.treeHeight=node.treeHeight;data._groupOper=this}}else{if(rootData){data=def.get(parentData._childrenByKey,node.key);if(data){data_addDatumsSimple.call(data,node.datums)}}if(!data){isNew=true;var index,siblings;if(rootData&&(siblings=parentData._children)){index=~def.array.binarySearch(siblings,node.datums[0],parentNode.groupLevelSpec.comparer)}data=new pvc.data.Data({parent:parentData,atoms:node.atoms,dimNames:node.dimNames,datums:node.datums,index:index})}}if(isNew&&node.isFlattenGroup){data._isFlattenGroup=true;data._isDegenerateFlattenGroup=!!node.isDegenerateFlattenGroup;var label=node.label;if(label){data.label+=label;data.absLabel+=label}}var childNodes=node.children;if(childNodes&&childNodes.length){if(isNew){data._groupSpec=node.groupSpec;data._groupLevelSpec=node.groupLevelSpec}childNodes.forEach(function(childNode){this._generateData(childNode,node,data,rootData)},this)}else if(isNew&&!node.isRoot){var leafs=data.root._leafs;data.leafIndex=leafs.length;leafs.push(data)}return data}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/GroupingSpec.js b/pacotes/ccc2/compacto/GroupingSpec.js deleted file mode 100755 index 2af9dbd..0000000 --- a/pacotes/ccc2/compacto/GroupingSpec.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.GroupingSpec').init(function(levelSpecs,type,keyArgs){this.type=type||null;var ids=[];this.hasCompositeLevels=false;var dimNames=[];this.levels=def.query(levelSpecs||undefined).where(function(levelSpec){return levelSpec.dimensions.length>0}).select(function(levelSpec){ids.push(levelSpec.id);def.array.append(dimNames,levelSpec.dimensionNames());if(!this.hasCompositeLevels&&levelSpec.dimensions.length>1){this.hasCompositeLevels=true}levelSpec._setAccDimNames(dimNames.slice(0));return levelSpec},this).array();this._dimNames=dimNames;this.depth=this.levels.length;this.isSingleLevel=this.depth===1;this.isSingleDimension=this.isSingleLevel&&!this.hasCompositeLevels;this.firstDimension=this.depth>0?this.levels[0].dimensions[0]:null;this.flatteningMode=def.get(keyArgs,'flatteningMode')||null;this.flattenRootLabel=def.get(keyArgs,'flattenRootLabel')||'';this.id=(this.flatteningMode||'')+"##"+this.flattenRootLabel+"##"+ids.join('||')}).add({bind:function(type){this.type=type||def.fail.argumentRequired('type');this.levels.forEach(function(levelSpec){levelSpec.bind(type)})},dimensions:function(){return def.query(this.levels).selectMany(function(level){return level.dimensions})},dimensionNames:function(){return this._dimNames},view:function(complex){return complex.view(this.dimensionNames())},isDiscrete:function(){var d;return!this.isSingleDimension||(!!(d=this.firstDimension)&&d.type.isDiscrete)},firstDimensionType:function(){var d=this.firstDimension;return d&&d.type},firstDimensionName:function(){var dt=this.firstDimensionType();return dt&&dt.name},firstDimensionValueType:function(){var dt=this.firstDimensionType();return dt&&dt.valueType},isNull:function(){return!this.levels.length},ensure:function(keyArgs){var grouping=this,flatteningMode=def.get(keyArgs,'flatteningMode');if(flatteningMode){if(flatteningMode==='singleLevel'){return grouping.singleLevelGrouping(keyArgs)}var flattenRootLabel=def.get(keyArgs,'flattenRootLabel')||'';if(this.flatteningMode!==flatteningMode||(this.flattenRootLabel!==flattenRootLabel)){grouping=new pvc.data.GroupingSpec(grouping.levels,grouping.type,{flatteningMode:flatteningMode,flattenRootLabel:flattenRootLabel})}}if(def.get(keyArgs,'reverse',false)){grouping=grouping.reversed()}return grouping},singleLevelGrouping:function(keyArgs){var reverse=!!def.get(keyArgs,'reverse',false);if(this.isSingleLevel&&!reverse){return this}this._singleLevelGrouping||(this._singleLevelGrouping={});var singleLevel=this._singleLevelGrouping[reverse];if(!singleLevel){var dimSpecs=this.dimensions().select(function(dimSpec){return reverse?new pvc.data.GroupingDimensionSpec(dimSpec.name,!dimSpec.reverse,dimSpec.type.complexType):dimSpec});var levelSpec=new pvc.data.GroupingLevelSpec(dimSpecs,this.type);singleLevel=new pvc.data.GroupingSpec([levelSpec],this.type,{flatteningMode:this.flatteningMode});this._singleLevelGrouping[reverse]=singleLevel}return singleLevel},reversed:function(){var reverseGrouping=this._reverseGrouping;if(!reverseGrouping){var levelSpecs=def.query(this.levels).select(function(levelSpec){var dimSpecs=def.query(levelSpec.dimensions).select(function(dimSpec){return new pvc.data.GroupingDimensionSpec(dimSpec.name,!dimSpec.reverse,dimSpec.type.complexType)});return new pvc.data.GroupingLevelSpec(dimSpecs,this.type)});reverseGrouping=new pvc.data.GroupingSpec(levelSpecs,this.type,{flatteningMode:this.flatteningMode});this._reverseGrouping=reverseGrouping}return reverseGrouping},toString:function(){return def.query(this.levels).select(function(level){return''+level}).array().join(', ')}});def.type('pvc.data.GroupingLevelSpec').init(function(dimSpecs,type){var ids=[];var dimNames=[];this.dimensions=def.query(dimSpecs).select(function(dimSpec){ids.push(dimSpec.id);dimNames.push(dimSpec.name);return dimSpec}).array();this._dimNames=dimNames;this.dimensionsInDefOrder=this.dimensions.slice(0);if(type){this._sortDimensions(type)}this.id=ids.join(',');this.depth=this.dimensions.length;var me=this;this.comparer=function(a,b){return me.compare(a,b)}}).add({_sortDimensions:function(type){type.sortDimensionNames(this.dimensionsInDefOrder,function(d){return d.name})},_setAccDimNames:function(accDimNames){this._accDimNames=accDimNames},accDimensionNames:function(){return this._accDimNames},dimensionNames:function(){return this._dimNames},bind:function(type){this._sortDimensions(type);this.dimensions.forEach(function(dimSpec){dimSpec.bind(type)})},compare:function(a,b){for(var i=0,D=this.depth;i1){var position=this.option('Position');var margins=def.set({},pvc.BasePanel.oppositeAnchor[position],5);optionInfo.defaultValue(margins)}return true}},cast:pvc.Sides.as},Paddings:{resolve:'_resolveFull',cast:pvc.Sides.as,value:5},Font:{resolve:'_resolveFull',cast:String,value:'10px sans-serif'}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Line.js b/pacotes/ccc2/compacto/Line.js deleted file mode 100755 index 42c7a4a..0000000 --- a/pacotes/ccc2/compacto/Line.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.Line',pvc.visual.Sign).init(function(panel,protoMark,keyArgs){var pvMark=protoMark.add(pv.Line);this.base(panel,pvMark,keyArgs);this.lock('segmented','smart').lock('antialias',true);if(!def.get(keyArgs,'freePosition',false)){var basePosProp=panel.isOrientationVertical()?"left":"bottom",orthoPosProp=panel.anchorOrtho(basePosProp);this._lockDynamic(orthoPosProp,'y')._lockDynamic(basePosProp,'x')}this._bindProperty('strokeStyle','strokeColor','color')._bindProperty('lineWidth','strokeWidth')}).prototype.property('strokeWidth').constructor.add({_addInteractive:function(keyArgs){keyArgs=def.setDefaults(keyArgs,'noTooltip',true);this.base(keyArgs)},y:function(){return 0},x:function(){return 0},defaultStrokeWidth:function(){return 1.5},interactiveStrokeWidth:function(strokeWidth){if(this.isActiveSeriesAware&&this.scene.isActiveSeries()){return Math.max(1,strokeWidth)*2.5}return strokeWidth},interactiveColor:function(color,type){var scene=this.scene;if(this.showsSelection()&&scene.anySelected()&&!scene.isSelected()){if(this.isActiveSeriesAware&&scene.isActiveSeries()){return pv.Color.names.darkgray.darker().darker()}if(type==='stroke'){return this.dimColor(color,type)}}return this.base(color,type)}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/LinearInterpolationOper.js b/pacotes/ccc2/compacto/LinearInterpolationOper.js deleted file mode 100755 index 79afa92..0000000 --- a/pacotes/ccc2/compacto/LinearInterpolationOper.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.LinearInterpolationOper').init(function(allPartsData,data,catRole,serRole,valRole,stretchEnds){this._newDatums=[];this._data=data;var allCatDataRoot=allPartsData.flattenBy(catRole,{ignoreNulls:false});var allCatDatas=allCatDataRoot._children;var serDatas1=this._serDatas1=serRole.isBound()?data.flattenBy(serRole).children().array():[null];this._isCatDiscrete=catRole.grouping.isDiscrete();this._firstCatDim=!this._isCatDiscrete?data.owner.dimensions(catRole.firstDimensionName()):null;this._stretchEnds=stretchEnds;var valDim=this._valDim=data.owner.dimensions(valRole.firstDimensionName());var visibleKeyArgs={visible:true,zeroIfNone:false};this._catInfos=allCatDatas.map(function(allCatData,catIndex){var catData=data._childrenByKey[allCatData.key];var catInfo={data:catData||allCatData,value:allCatData.value,isInterpolated:false,serInfos:null,index:catIndex};catInfo.serInfos=serDatas1.map(function(serData1){var group=catData;if(group&&serData1){group=group._childrenByKey[serData1.key]}var value=group?group.dimensions(valDim.name).sum(visibleKeyArgs):null;return{data:serData1,group:group,value:value,isNull:value==null,catInfo:catInfo}},this);return catInfo});this._serCount=serDatas1.length;this._serStates=def.range(0,this._serCount).select(function(serIndex){return new pvc.data.LinearInterpolationOperSeriesState(this,serIndex)},this).array()}).add({interpolate:function(){var catInfo;while((catInfo=this._catInfos.shift())){catInfo.serInfos.forEach(this._visitSeries,this)}var newDatums=this._newDatums;if(newDatums.length){this._data.owner.add(newDatums)}},_visitSeries:function(catSerInfo,serIndex){this._serStates[serIndex].visit(catSerInfo)},nextUnprocessedNonNullCategOfSeries:function(serIndex){var catIndex=0,catCount=this._catInfos.length;while(catIndex=2)||def.assert("Must have at least one interpolation point.");this._stepValue=deltaValue/stepCount;this._middleIndex=~~(stepCount/2); var dotCount=(stepCount-1);this._isOdd=(dotCount%2)>0}else{var fromCat=+last.catInfo.value;var toCat=+next.catInfo.value;var deltaCat=toCat-fromCat;this._steep=deltaValue/deltaCat; this._middleCat=(toCat+fromCat)/2}}},_interpolate:function(catSerInfo){this._initInterpData();var next=this.__nextNonNull;var last=this.__lastNonNull;var one=next||last;if(!one){return}var value,group;var interpolation=this.interpolation;var catInfo=catSerInfo.catInfo;if(next&&last){if(interpolation._isCatDiscrete){var groupIndex=(catInfo.index-last.catInfo.index);value=last.value+this._stepValue*groupIndex;if(this._isOdd){group=groupIndex0;i++){var row=source[i];var m=0;while(m10){out.push(' ...')}out.push("COLS ("+this.J+")");var colTypes=this._columnTypes;this.metadata.forEach(function(col,j){out.push(" ["+j+"] "+"'"+col.colName+"' ("+"type: "+col.colType+", "+"inspected: "+(colTypes[j]?'continuous':'discrete')+(col.colLabel?(", label: '"+col.colLabel+"'"):"")+")")});pvc.log(out.join('\n'))},_createPlot2SeriesKeySet:function(plot2SeriesIndexes,seriesKeys){var plot2SeriesKeySet=null,seriesCount=seriesKeys.length;def.query(plot2SeriesIndexes).each(function(indexText){var seriesIndex=+indexText;if(isNaN(seriesIndex)){throw def.error.argumentInvalid('plot2SeriesIndexes',"Element is not a number '{0}'.",[indexText])}if(seriesIndex<0){if(seriesIndex<=-seriesCount){throw def.error.argumentInvalid('plot2SeriesIndexes',"Index is out of range '{0}'.",[seriesIndex])}seriesIndex=seriesCount+seriesIndex}else if(seriesIndex>=seriesCount){throw def.error.argumentInvalid('plot2SeriesIndexes',"Index is out of range '{0}'.",[seriesIndex])}if(!plot2SeriesKeySet){plot2SeriesKeySet={}}plot2SeriesKeySet[seriesKeys[seriesIndex]]=true});return plot2SeriesKeySet},_dataPartGet:function(calcAxis2SeriesKeySet,seriesReader){var me=this;var dataPartDimName=this.options.dataPartDimName;var dataPartDimension,plot2SeriesKeySet,part1Atom,part2Atom,outAtomsSeries={};function dataPartGet(item,outAtoms){if(!dataPartDimension){plot2SeriesKeySet=calcAxis2SeriesKeySet();dataPartDimension=me.data.dimensions(dataPartDimName);if(pvc.debug>=3&&plot2SeriesKeySet){pvc.log("Second axis series values: "+pvc.stringify(def.keys(plot2SeriesKeySet)))}}var partAtom;seriesReader(item,outAtomsSeries);var series=outAtomsSeries.series;if(series!=null&&series.v!=null){series=series.v}if(def.hasOwn(plot2SeriesKeySet,series)){partAtom=part2Atom||(part2Atom=dataPartDimension.intern("1"))}else{partAtom=part1Atom||(part1Atom=dataPartDimension.intern("0"))}outAtoms[dataPartDimName]=partAtom}return dataPartGet}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/MetricPointChartTranslationOper.js b/pacotes/ccc2/compacto/MetricPointChartTranslationOper.js deleted file mode 100755 index 9d0a830..0000000 --- a/pacotes/ccc2/compacto/MetricPointChartTranslationOper.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.MetricPointChartTranslationOper').add({_meaLayoutRoles:['x','y','color','size'],configureType:function(){var itemTypes=this._itemTypes;var V=itemTypes.length;var freeMeaIndexes=[];var freeDisIndexes=[];def.range(0,V).each(function(j){if(!this._userUsedIndexes[j]){if(itemTypes[j]===1){freeMeaIndexes.push(j)}else{freeDisIndexes.push(j)}}},this);var N;var autoDimNames=[];var F=freeMeaIndexes.length;if(F>0){var R=this._meaLayoutRoles.length;var i=0;while(i0){freeMeaIndexes.length=N;this.defReader({names:autoDimNames,indexes:freeMeaIndexes})}}F=freeDisIndexes.length;if(F>0){autoDimNames.length=0;this._getUnboundRoleDefaultDimNames('series',F,autoDimNames);N=autoDimNames.length;if(N>0){freeDisIndexes.length=N;this.defReader({names:autoDimNames,indexes:freeDisIndexes})}}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/MetricPointPlot.js b/pacotes/ccc2/compacto/MetricPointPlot.js deleted file mode 100755 index 604ef4c..0000000 --- a/pacotes/ccc2/compacto/MetricPointPlot.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.MetricPointPlot',pvc.visual.MetricXYPlot).add({type:'scatter',_getOptionsDefinition:function(){return pvc.visual.MetricPointPlot.optionsDef}});function visibleData(type){return{resolveV1:function(optionInfo){this._specifyChartOption(optionInfo,'show'+type);return true}}}pvc.visual.MetricPointPlot.optionsDef=def.create(pvc.visual.MetricXYPlot.optionsDef,{SizeRole:{resolve:'_resolveFixed',value:'size'},SizeAxis:{resolve:'_resolveFixed',value:1},Shape:{resolve:'_resolveFull',cast:pvc.parseShape,value:'circle'},DotsVisible:{resolve:'_resolveFull',data:visibleData('Dots'),cast:Boolean,value:false},LinesVisible:{resolve:'_resolveFull',data:visibleData('Lines'),cast:Boolean,value:false},ValuesAnchor:{value:'right'}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/MetricXYPlot.js b/pacotes/ccc2/compacto/MetricXYPlot.js deleted file mode 100755 index 3c94784..0000000 --- a/pacotes/ccc2/compacto/MetricXYPlot.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.MetricXYPlot',pvc.visual.CartesianPlot).add({_getOptionsDefinition:function(){return pvc.visual.MetricXYPlot.optionsDef}});pvc.visual.MetricXYPlot.optionsDef=def.create(pvc.visual.CartesianPlot.optionsDef,{BaseRole:{value:'x'},OrthoAxis:{resolve:null},OrthoRole:{value:'y'}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/NormalizedBarPlot.js b/pacotes/ccc2/compacto/NormalizedBarPlot.js deleted file mode 100755 index 8b4cf9a..0000000 --- a/pacotes/ccc2/compacto/NormalizedBarPlot.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.NormalizedBarPlot',pvc.visual.BarPlotAbstract).add({type:'bar',_getOptionsDefinition:function(){return pvc.visual.NormalizedBarPlot.optionsDef}});pvc.visual.NormalizedBarPlot.optionsDef=def.create(pvc.visual.BarPlotAbstract.optionsDef,{Stacked:{resolve:null,value:true}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/OptionsBase.js b/pacotes/ccc2/compacto/OptionsBase.js deleted file mode 100755 index 55208c6..0000000 --- a/pacotes/ccc2/compacto/OptionsBase.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.OptionsBase').init(function(chart,type,index,keyArgs){this.chart=chart;this.type=type;this.index=index==null?0:index;this.name=def.get(keyArgs,'name');this.id=this._buildId();this.optionId=this._buildOptionId();var rs=this._resolvers=[];this._registerResolversFull(rs,keyArgs);this.option=pvc.options(this._getOptionsDefinition(),this)}).add({_buildId:function(){return pvc.buildIndexedId(this.type,this.index)},_buildOptionId:function(){return this.id},_getOptionsDefinition:def.method({isAbstract:true}),_chartOption:function(name){return this.chart.options[name]},_registerResolversFull:function(rs,keyArgs){var fixed=def.get(keyArgs,'fixed');if(fixed){this._fixed=fixed;rs.push(pvc.options.specify(function(optionInfo){return fixed[optionInfo.name]}))}this._registerResolversNormal(rs,keyArgs);var defaults=def.get(keyArgs,'defaults');if(defaults){this._defaults=defaults}rs.push(this._resolveDefault)},_registerResolversNormal:function(rs,keyArgs){if(this.chart.compatVersion()<=1){rs.push(this._resolveByV1OnlyLogic)}if(this.name){rs.push(pvc.options.specify(function(optionInfo){return this._chartOption(this.name+def.firstUpperCase(optionInfo.name))}))}rs.push(this._resolveByOptionId);if(def.get(keyArgs,'byNaked',!this.index)){rs.push(this._resolveByNaked)}},_resolveFull:function(optionInfo){var rs=this._resolvers;for(var i=0,L=rs.length;i=2){pvc.log("[Warning] Invalid 'ValuesLabelStyle' value: '"+value+"'.")}return'linked'},value:'linked'},ValuesMask:{resolve:'_resolveFull',data:{resolveDefault:function(optionInfo){optionInfo.defaultValue(this.option('ValuesLabelStyle')==='linked'?"{value} ({value.percent})":"{value}");return true}}},LinkInsetRadius:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:new pvc.PercentValue(0.05)},LinkOutsetRadius:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:new pvc.PercentValue(0.025)},LinkMargin:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:new pvc.PercentValue(0.025)},LinkHandleWidth:{resolve:'_resolveFull',cast:pvc.castNumber,value:0.5},LinkLabelSize:{resolve:'_resolveFull',cast:pvc.PercentValue.parse,value:new pvc.PercentValue(0.15)},LinkLabelSpacingMin:{resolve:'_resolveFull',cast:pvc.castNumber,value:0.5}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/PieSlice.js b/pacotes/ccc2/compacto/PieSlice.js deleted file mode 100755 index 4363d60..0000000 --- a/pacotes/ccc2/compacto/PieSlice.js +++ /dev/null @@ -1 +0,0 @@ -pv.PieSlice=function(){pv.Wedge.call(this)};pv.PieSlice.prototype=pv.extend(pv.Wedge);pv.PieSlice.prototype.midAngle=function(){var instance=this.instance();return instance.startAngle+(instance.angle/2)};def.type('pvc.visual.PieSlice',pvc.visual.Sign).init(function(panel,protoMark,keyArgs){var pvMark=protoMark.add(pv.PieSlice);keyArgs=def.setDefaults(keyArgs,'freeColor',false);this.base(panel,pvMark,keyArgs);this._activeOffsetRadius=def.get(keyArgs,'activeOffsetRadius',0);this._center=def.get(keyArgs,'center');this.optional('lineWidth',0.6)._bindProperty('angle','angle')._lockDynamic('bottom','y')._lockDynamic('left','x').lock('top',null).lock('right',null)}).prototype.property('offsetRadius').constructor.add({angle:function(){return 0},x:function(){return this._center.x+this._offsetSlice('cos')},y:function(){return this._center.y-this._offsetSlice('sin')},_offsetSlice:function(fun){var offset=this._getOffsetRadius();if(offset!==0){offset=offset*Math[fun](this.pvMark.midAngle())}return offset},_getOffsetRadius:function(){var offset=this.state.offsetRadius;if(offset==null){offset=(this.state.offsetRadius=this.offsetRadius()||0)}return offset},defaultColor:function(type){if(type==='stroke'){return null}return this.base(type)},interactiveColor:function(color,type){var scene=this.scene;if(scene.isActive){switch(type){case'fill':return color.brighter(0.2).alpha(0.8);case'stroke':return color.brighter(1.3).alpha(0.7)}}else if(this.showsSelection()&&scene.anySelected()&&!scene.isSelected()){if(type==='fill'){return this.dimColor(color,type)}}return this.base(color,type)},baseOffsetRadius:function(){return 0},interactiveOffsetRadius:function(offsetRadius){if(this.scene.isActive){return offsetRadius+this._activeOffsetRadius}return offsetRadius}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Plot.js b/pacotes/ccc2/compacto/Plot.js deleted file mode 100755 index f745122..0000000 --- a/pacotes/ccc2/compacto/Plot.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.Plot',pvc.visual.OptionsBase).init(function(chart,keyArgs){var typePlots=def.getPath(chart,['plotsByType',this.type]);var index=typePlots?typePlots.length:0;var globalIndex=chart.plotList.length;keyArgs=def.set(keyArgs,'byNaked',!globalIndex);this.base(chart,this.type,index,keyArgs);chart._addPlot(this);var prefixes=this.extensionPrefixes=[this.id];if(!this.globalIndex){prefixes.push('')}if(this.name){prefixes.push(this.name)}}).add({_getOptionsDefinition:function(){return pvc.visual.Plot.optionsDef},_resolveByNaked:pvc.options.specify(function(optionInfo){if(!this.globalIndex){return this._chartOption(def.firstLowerCase(optionInfo.name))}})});pvc.visual.Plot.optionsDef={Orientation:{resolve:function(optionInfo){optionInfo.specify(this._chartOption('orientation')||'vertical');return true},cast:String},ValuesVisible:{resolve:'_resolveFull',data:{resolveV1:function(optionInfo){if(this.globalIndex===0){var show=this._chartOption('showValues');if(show!==undefined){optionInfo.specify(show)}else{show=this.type!=='point';optionInfo.defaultValue(show)}return true}}},cast:Boolean,value:false},ValuesAnchor:{resolve:'_resolveFull',cast:pvc.parseAnchor},ValuesFont:{resolve:'_resolveFull',cast:String,value:'10px sans-serif'},ValuesMask:{resolve:'_resolveFull',cast:String,value:"{value}"},DataPart:{resolve:'_resolveFixed',cast:String,value:'0'},ColorRole:{resolve:'_resolveFixed',cast:String,value:'color'},ColorAxis:{resolve:pvc.options.resolvers([function(optionInfo){if(this.globalIndex===0){optionInfo.specify(1);return true}},'_resolveFull']),cast:function(value){value=pvc.castNumber(value);if(value!=null){value=def.between(value,1,10)}else{value=1}return value},value:1}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/PointPlot.js b/pacotes/ccc2/compacto/PointPlot.js deleted file mode 100755 index f51a164..0000000 --- a/pacotes/ccc2/compacto/PointPlot.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){def.type('pvc.visual.PointPlot',pvc.visual.CategoricalPlot).add({type:'point',_getOptionsDefinition:function(){return pvc.visual.PointPlot.optionsDef}});function visibleData(type,dv){return{resolveV1:function(optionInfo){if(this.globalIndex===0){if(!this._specifyChartOption(optionInfo,'show'+type)){optionInfo.defaultValue(dv)}return true}}}}pvc.visual.PointPlot.optionsDef=def.create(pvc.visual.CategoricalPlot.optionsDef,{DotsVisible:{resolve:'_resolveFull',data:visibleData('Dots',true),cast:Boolean,value:false},LinesVisible:{resolve:'_resolveFull',data:visibleData('Lines',true),cast:Boolean,value:false},AreasVisible:{resolve:'_resolveFull',data:visibleData('Areas',false),cast:Boolean,value:false},ValuesAnchor:{value:'right'}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/RelationalTranslationOper.js b/pacotes/ccc2/compacto/RelationalTranslationOper.js deleted file mode 100755 index 581dc5a..0000000 --- a/pacotes/ccc2/compacto/RelationalTranslationOper.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.RelationalTranslationOper',pvc.data.MatrixTranslationOper).add({M:0,C:0,S:0,_processMetadata:function(){this.base();var metadata=this.metadata;var J=this.J;var C=this.options.categoriesCount;if(C!=null&&(!isFinite(C)||C<0)){C=0}var S;var valuesColIndexes,M;if(this.options.isMultiValued){valuesColIndexes=pvc.parseDistinctIndexArray(this.options.measuresIndexes,J-1);M=valuesColIndexes?valuesColIndexes.length:0}var D;if(M==null){if(J>0&&J<=3&&(C==null||C===1)&&S==null){M=1;valuesColIndexes=[J-1];C=J>=2?1:0;S=J>=3?1:0;D=C+S}else if(C!=null&&C>=J){D=J;C=J;S=0;M=0}else{var Mmax=C!=null?(J-C):Infinity;valuesColIndexes=def.query(metadata).where(function(colDef,index){return this._columnTypes[index]!==0},this).select(function(colDef){return colDef.colIndex}).take(Mmax).array();M=valuesColIndexes.length}}if(D==null){D=J-M;if(D===0){S=C=0}else if(C!=null){if(C>D){C=D;S=0}else{S=D-C}}else{S=D>1?1:0;C=D-S}}var seriesInRows=this.options.seriesInRows;var colGroupSpecs=[];if(D){if(S&&!seriesInRows){colGroupSpecs.push({name:'S',count:S})}if(C){colGroupSpecs.push({name:'C',count:C})}if(S&&seriesInRows){colGroupSpecs.push({name:'S',count:S})}}if(M){colGroupSpecs.push({name:'M',count:M})}var availableInputIndexes=def.range(0,J).array();if(valuesColIndexes){valuesColIndexes.forEach(function(inputIndex){availableInputIndexes.splice(inputIndex,1)})}var specsByName={};colGroupSpecs.forEach(function(groupSpec){var count=groupSpec.count;var name=groupSpec.name;specsByName[name]=groupSpec;if(valuesColIndexes&&name==='M'){groupSpec.indexes=valuesColIndexes}else{groupSpec.indexes=availableInputIndexes.splice(0,count)}},this);this.M=M;this.S=S;this.C=C;var itemPerm=[];['S','C','M'].forEach(function(name){var groupSpec=specsByName[name];if(groupSpec){def.array.append(itemPerm,groupSpec.indexes)}});var colTypes=this._columnTypes;this._itemTypes=itemPerm.map(function(index){return colTypes[index]});this._itemCrossGroupIndex={S:0,C:this.S,M:this.S+this.C};this._itemPerm=itemPerm;if(pvc.debug>=3){var out=["RELATIONAL TRANSLATOR MAPPING",pvc.logSeparator,"["+colGroupSpecs.map(function(groupSpec){return def.array.create(groupSpec.count,groupSpec.name).join('')}).join(' ')+"]"];pvc.log(out.join("\n"))}},_configureTypeCore:function(){var me=this;var index=0;var dimsReaders=[];function add(dimGroupName,colGroupName,level,count){var groupEndIndex=me._itemCrossGroupIndex[colGroupName]+count;while(count>0){var dimName=pvc.buildIndexedId(dimGroupName,level);if(!me.complexTypeProj.isReadOrCalc(dimName)){index=me._nextAvailableItemIndex(index);if(index>=groupEndIndex){return}dimsReaders.push({names:dimName,indexes:index});index++;count--}level++}}if(this.S>0){add('series','S',0,this.S)}if(this.C>0){add('category','C',0,this.C)}if(this.M>0){add('value','M',0,this.M)}if(dimsReaders){dimsReaders.forEach(this.defReader,this)}var plot2SeriesIndexes=this.options.plot2SeriesIndexes;if(plot2SeriesIndexes!=null){var seriesReader=this._userDimsReadersByDim.series;if(seriesReader){var dataPartDimName=this.options.dataPartDimName;this._userRead(relTransl_dataPartGet.call(this,plot2SeriesIndexes,seriesReader),dataPartDimName)}}},_executeCore:function(){var dimsReaders=this._getDimensionsReaders();var permIndexes=this._itemPerm;return def.query(this._getItems()).select(function(item){item=pv.permute(item,permIndexes);return this._readItem(item,dimsReaders)},this)}});function relTransl_dataPartGet(plot2SeriesIndexes,seriesReader){var me=this;function calcAxis2SeriesKeySet(){var atoms={};var seriesKeys=def.query(me.source).select(function(item){seriesReader(item,atoms);var value=atoms.series;if(value!=null&&value.v!=null){value=value.v}return value||null}).distinct().array();return me._createPlot2SeriesKeySet(plot2SeriesIndexes,seriesKeys)}return this._dataPartGet(calcAxis2SeriesKeySet,seriesReader)} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Role.js b/pacotes/ccc2/compacto/Role.js deleted file mode 100755 index cbbbd33..0000000 --- a/pacotes/ccc2/compacto/Role.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.Role').init(function(name,keyArgs){this.name=name;this.label=def.get(keyArgs,'label')||pvc.buildTitleFromName(name);this.index=def.get(keyArgs,'index')||0;this.dimensionDefaults=def.get(keyArgs,'dimensionDefaults')||{};if(def.get(keyArgs,'isRequired',false)){this.isRequired=true}if(def.get(keyArgs,'autoCreateDimension',false)){this.autoCreateDimension=true}var defaultSourceRoleName=def.get(keyArgs,'defaultSourceRole');if(defaultSourceRoleName){this.defaultSourceRoleName=defaultSourceRoleName}var defaultDimensionName=def.get(keyArgs,'defaultDimension');if(defaultDimensionName){this.defaultDimensionName=defaultDimensionName}if(!defaultDimensionName&&this.autoCreateDimension){throw def.error.argumentRequired('defaultDimension')}var requireSingleDimension;var requireIsDiscrete=def.get(keyArgs,'requireIsDiscrete');if(requireIsDiscrete!=null){if(!requireIsDiscrete){requireSingleDimension=true}}if(requireSingleDimension!=null){requireSingleDimension=def.get(keyArgs,'requireSingleDimension',false);if(requireSingleDimension){if(def.get(keyArgs,'isMeasure',false)){this.isMeasure=true;if(def.get(keyArgs,'isPercent',false)){this.isPercent=true}}var valueType=def.get(keyArgs,'valueType',null);if(valueType!==this.valueType){this.valueType=valueType;this.dimensionDefaults.valueType=valueType}}}if(requireSingleDimension!==this.requireSingleDimension){this.requireSingleDimension=requireSingleDimension}if(requireIsDiscrete!=this.requireIsDiscrete){this.requireIsDiscrete=!!requireIsDiscrete;this.dimensionDefaults.isDiscrete=this.requireIsDiscrete}var flatteningMode=def.get(keyArgs,'flatteningMode');if(flatteningMode&&flatteningMode!=this.flatteningMode){this.flatteningMode=flatteningMode}}).add({isRequired:false,requireSingleDimension:false,valueType:null,requireIsDiscrete:null,isMeasure:false,isPercent:false,defaultSourceRoleName:null,defaultDimensionName:null,grouping:null,flatteningMode:'singleLevel',flattenRootLabel:'',autoCreateDimension:false,isReversed:false,label:null,sourceRole:null,firstDimensionType:function(){var g=this.grouping;return g&&g.firstDimensionType()},firstDimensionName:function(){var g=this.grouping;return g&&g.firstDimensionName()},firstDimensionValueType:function(){var g=this.grouping;return g&&g.firstDimensionValueType()},isDiscrete:function(){var g=this.grouping;return g&&g.isDiscrete()},setSourceRole:function(sourceRole){this.sourceRole=sourceRole},setIsReversed:function(isReversed){if(!isReversed){delete this.isReversed}else{this.isReversed=true}},setFlatteningMode:function(flatteningMode){if(!flatteningMode||flatteningMode==='singleLevel'){delete this.flatteningMode}else{this.flatteningMode=flatteningMode}},setFlattenRootLabel:function(flattenRootLabel){if(!flattenRootLabel){delete this.flattenRootLabel}else{this.flattenRootLabel=flattenRootLabel}},flatten:function(data,keyArgs){if(this.grouping){return data.flattenBy(this,keyArgs)}},flattenedGrouping:function(keyArgs){var grouping=this.grouping;if(grouping){keyArgs=def.setDefaults(keyArgs,'flatteningMode',this.flatteningMode,'flattenRootLabel',this.flattenRootLabel);return grouping.ensure(keyArgs)}},select:function(data,keyArgs){var grouping=this.grouping;if(grouping){return data.groupBy(grouping.ensure(keyArgs),keyArgs)}},view:function(complex){var grouping=this.grouping;if(grouping){return grouping.view(complex)}},preBind:function(groupingSpec){this.__grouping=groupingSpec;return this},isPreBound:function(){return!!this.__grouping},preBoundGrouping:function(){return this.__grouping},isBound:function(){return!!this.grouping},postBind:function(type){var grouping=this.__grouping;if(grouping){delete this.__grouping;grouping.bind(type);this.bind(grouping)}return this},bind:function(groupingSpec){if(groupingSpec){if(groupingSpec.isNull()){groupingSpec=null}else{if(this.requireSingleDimension&&!groupingSpec.isSingleDimension){throw def.error.operationInvalid("Role '{0}' only accepts a single dimension.",[this.name])}var valueType=this.valueType;var requireIsDiscrete=this.requireIsDiscrete;groupingSpec.dimensions().each(function(dimSpec){var dimType=dimSpec.type;if(valueType&&dimType.valueType!==valueType){throw def.error.operationInvalid("Role '{0}' cannot be bound to dimension '{1}'. \nIt only accepts dimensions of type '{2}' and not of type '{3}'.",[this.name,dimType.name,pvc.data.DimensionType.valueTypeName(valueType),dimType.valueTypeName])}if(requireIsDiscrete!=null&&dimType.isDiscrete!==requireIsDiscrete){if(requireIsDiscrete){dimType._toDiscrete()}else{throw def.error.operationInvalid("Role '{0}' cannot be bound to dimension '{1}'. \nIt only accepts {2} dimensions.",[this.name,dimType.name,requireIsDiscrete?'discrete':'continuous'])}}},this)}}if(this.grouping){this.grouping.dimensions().each(function(dimSpec){if(dimSpec.type){dimType_removeVisualRole.call(dimSpec.type,this)}},this)}this.grouping=groupingSpec;if(this.grouping){if(this.isReversed){this.grouping=this.grouping.reversed()}this.grouping.dimensions().each(function(dimSpec){dimType_addVisualRole.call(dimSpec.type,this)},this)}return this}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Rule.js b/pacotes/ccc2/compacto/Rule.js deleted file mode 100755 index e82c341..0000000 --- a/pacotes/ccc2/compacto/Rule.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.Rule',pvc.visual.Sign).init(function(panel,parentMark,keyArgs){var pvMark=parentMark.add(pv.Rule);var protoMark=def.get(keyArgs,'proto');if(protoMark){pvMark.extend(protoMark)}this.base(panel,pvMark,keyArgs);if(!def.get(keyArgs,'freeStyle')){this._bindProperty('strokeStyle','strokeColor','color')._bindProperty('lineWidth','strokeWidth')}}).prototype.property('strokeWidth').constructor.add({_addInteractive:function(keyArgs){keyArgs=def.setDefaults(keyArgs,'noHover',true,'noSelect',true,'noTooltip',true,'noClick',true,'noDoubleClick',true);this.base(keyArgs)},defaultStrokeWidth:function(){return 1},interactiveStrokeWidth:function(strokeWidth){if(this.scene.isActive){return Math.max(1,strokeWidth)*2.2}return strokeWidth},interactiveColor:function(color,type){var scene=this.scene;if(!scene.isActive&&this.showsSelection()&&scene.anySelected()&&scene.datum&&!scene.isSelected()){return this.dimColor(color,type)}return this.base(color,type)}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Scene.js b/pacotes/ccc2/compacto/Scene.js deleted file mode 100755 index a1810d5..0000000 --- a/pacotes/ccc2/compacto/Scene.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.Scene').init(function(parent,keyArgs){if(pvc.debug>=4){this.id=def.nextId('scene')}this._renderId=0;this.renderState={};pv.Dom.Node.call(this,null);this.parent=parent||null;this.root=this;if(parent){var index=def.get(keyArgs,'index',null);parent.insertAt(this,index);this.root=parent.root}else{this._active=null;this._panel=def.get(keyArgs,'panel')||def.fail.argumentRequired('panel',"Argument is required on root scene.")}var group=def.get(keyArgs,'group',null),datum;if(group){datum=group._datums[0]}else{datum=def.get(keyArgs,'datum')}this.datum=datum||null;this.group=group;var parentAtoms;var source=(group||datum);this.atoms=source?source.atoms:(parentAtoms=(parent&&parent.atoms))?Object.create(parentAtoms):{};source=(datum||group);this.firstAtoms=source?source.atoms:(parentAtoms=(parent&&parent.firstAtoms))?Object.create(parentAtoms):this.atoms;if(!source){this.isNull=true}this.vars=parent?Object.create(parent.vars):{}}).add(pv.Dom.Node).add({isNull:false,datums:function(){return this.group?this.group.datums():(this.datum?def.query(this.datum):def.query())},format:function(mask){return def.format(mask,this._formatScope,this)},_formatScope:function(prop){if(prop.charAt(0)==='#'){prop=prop.substr(1).split('.');if(prop.length>2){throw def.error.operationInvalid("Scene format mask is invalid.")}var atom=this.atoms[prop[0]];if(atom){if(prop.length>1){switch(prop[1]){case'value':return atom.value;case'label':break;default:throw def.error.operationInvalid("Scene format mask is invalid.")}}return atom}return null}return def.getPath(this.vars,prop)},isRoot:function(){return this.root===this},panel:function(){return this.root._panel},chart:function(){return this.root._panel.chart},compatVersion:function(){return this.root._panel.compatVersion()},children:function(){if(!this.childNodes){return def.query()}return def.query(this.childNodes)},leafs:function(){function getFirstLeafFrom(leaf){while(leaf.childNodes.length){leaf=leaf.childNodes[0]}return leaf}var root=this;return def.query(function(nextIndex){if(!nextIndex){var item=getFirstLeafFrom(root);if(item===root){return 0}this.item=item;return 1}var next=this.item.nextSibling;if(next){this.item=next;return 1}var current=this.item;while((current!==root)&&(current=current.parentNode)){if((next=current.nextSibling)){this.item=getFirstLeafFrom(next);return 1}}return 0})},anyInteraction:function(){return(!!this.root._active||this.anySelected())},isActive:false,setActive:function(isActive){isActive=!!isActive;if(this.isActive!==isActive){rootScene_setActive.call(this.root,this.isActive?null:this)}},clearActive:function(){return rootScene_setActive.call(this.root,null)},anyActive:function(){return!!this.root._active},active:function(){return this.root._active},activeSeries:function(){var active=this.active();var seriesVar;return active&&(seriesVar=active.vars.series)&&seriesVar.value},isActiveSeries:function(){if(this.isActive){return true}var activeSeries;return(activeSeries=this.activeSeries())!=null&&(activeSeries===this.vars.series.value)},isSelected:function(){return this._selectedData().is},anySelected:function(){return this._selectedData().any},_selectedData:function(){return this.renderState._selectedData||(this.renderState._selectedData=this._createSelectedData())},_createSelectedData:function(){var any=this.panel().chart.data.owner.selectedCount()>0,isSelected=any&&this.datums().any(function(datum){return datum.isSelected});return{any:any,is:isSelected}}});function scene_renderId(renderId){if(this._renderId!==renderId){if(pvc.debug>=20){pvc.log({sceneId:this.id,oldRenderId:this._renderId,newRenderId:renderId})}this._renderId=renderId;this.renderState={}}}function rootScene_setActive(scene){var ownerScene;if(scene&&(ownerScene=scene.ownerScene)){scene=ownerScene}if(this._active!==scene){if(this._active){scene_setActive.call(this._active,false)}this._active=scene||null;if(this._active){scene_setActive.call(this._active,true)}return true}return false}function scene_setActive(isActive){isActive=!!isActive;if(this.isActive!==isActive){if(!isActive){delete this.isActive}else{this.isActive=true}}} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/Sign.js b/pacotes/ccc2/compacto/Sign.js deleted file mode 100755 index fae7cd4..0000000 --- a/pacotes/ccc2/compacto/Sign.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.visual.Sign',pvc.visual.BasicSign).init(function(panel,pvMark,keyArgs){this.base(panel,pvMark,keyArgs);this.bits=0;var extensionIds=def.get(keyArgs,'extensionId');if(extensionIds!=null){this.extensionAbsIds=def.array.to(panel._makeExtensionAbsId(extensionIds))}this.isActiveSeriesAware=def.get(keyArgs,'activeSeriesAware',true)&&!!this.chart.visualRoles('series',{assertExists:false});var wrapper=def.get(keyArgs,'wrapper');if(!wrapper){wrapper=function(f){return function(scene){return f.call(panel._getContext(pvMark),scene)}}}pvMark.wrapper(wrapper);if(!def.get(keyArgs,'freeColor',true)){this._bindProperty('fillStyle','fillColor','color')._bindProperty('strokeStyle','strokeColor','color')}}).postInit(function(panel,pvMark,keyArgs){panel._addSign(this);this._addInteractive(keyArgs)}).add({property:function(name){var upperName=def.firstUpperCase(name);var baseName='base'+upperName;var defName='default'+upperName;var normalName='normal'+upperName;var interName='interactive'+upperName;var methods={};methods[name]=function(arg){delete this._finished;var value;this._arg=arg;try{value=this[baseName](arg);if(value==null){return null}if(this.hasOwnProperty('_finished')){return value}if(this.showsInteraction()&&this.scene.anyInteraction()){value=this[interName](value,arg)}else{value=this[normalName](value,arg)}}finally{delete this._arg}return value};methods[baseName]=function(arg){return this.delegateExtension()};methods[defName]=function(arg){return};methods[normalName]=function(value,arg){return value};methods[interName]=function(value,arg){return value};this.constructor.add(methods);return this},finished:function(value){this._finished=true;return value},applyExtensions:function(){if(!this._extended){this._extended=true;var extensionAbsIds=this.extensionAbsIds;if(extensionAbsIds){extensionAbsIds.forEach(function(extensionAbsId){this.panel.extendAbs(this.pvMark,extensionAbsId)},this)}}return this},intercept:function(name,fun){return this._intercept(name,fun.bind(this))},lockDimensions:function(){this.pvMark.lock('left').lock('right').lock('top').lock('bottom').lock('width').lock('height');return this},_extensionKeyArgs:{tag:pvc.extensionTag},_bindProperty:function(pvName,prop,realProp){var me=this;if(!realProp){realProp=prop}var defaultPropName="default"+def.firstUpperCase(realProp);if(def.fun.is(this[defaultPropName])){if(!this.pvMark.hasDelegateValue(pvName,pvc.extensionTag)){var defaultMethodCaller=function(){return me[defaultPropName](me._arg)};this.pvMark.intercept(pvName,defaultMethodCaller,this._extensionKeyArgs)}}function mainMethodCaller(){return me[prop]()}return this._intercept(pvName,mainMethodCaller)},_intercept:function(name,fun){var mark=this.pvMark;var extensionAbsIds=this.extensionAbsIds;if(extensionAbsIds){def.query(extensionAbsIds).select(function(extensionAbsId){return this.panel._getExtensionAbs(extensionAbsId,name)},this).where(def.notUndef).each(function(extValue){extValue=mark.wrap(extValue,name);mark.intercept(name,extValue,this._extensionKeyArgs)},this)}(mark._intercepted||(mark._intercepted={}))[name]=true;mark.intercept(name,fun);return this}}).prototype.property('color').constructor.add({_bitShowsActivity:2,_bitShowsSelection:4,_bitShowsInteraction:4|2,_bitShowsTooltip:8,_bitSelectable:16,_bitHoverable:32,_bitClickable:64,_bitDoubleClickable:128,showsInteraction:function(){return(this.bits&this._bitShowsInteraction)!==0},showsActivity:function(){return(this.bits&this._bitShowsActivity)!==0},showsSelection:function(){return(this.bits&this._bitShowsSelection)!==0},showsTooltip:function(){return(this.bits&this._bitShowsTooltip)!==0},isSelectable:function(){return(this.bits&this._bitSelectable)!==0},isHoverable:function(){return(this.bits&this._bitHoverable)!==0},isClickable:function(){return(this.bits&this._bitClickable)!==0},isDoubleClickable:function(){return(this.bits&this._bitDoubleClickable)!==0},extensionAbsIds:null,_addInteractive:function(keyArgs){var panel=this.panel,pvMark=this.pvMark,chart=this.chart,options=chart.options;var bits=this.bits;bits|=this._bitShowsInteraction;if(chart._tooltipEnabled&&!def.get(keyArgs,'noTooltip')){bits|=this._bitShowsTooltip;this.panel._addPropTooltip(pvMark,def.get(keyArgs,'tooltipArgs'))}var clickSelectable=false;var clickable=false;if(options.selectable||options.hoverable){if(options.selectable&&!def.get(keyArgs,'noSelect')){bits|=this._bitSelectable;clickSelectable=!def.get(keyArgs,'noClickSelect')&&chart._canSelectWithClick()}if(options.hoverable&&!def.get(keyArgs,'noHover')){bits|=this._bitHoverable;panel._addPropHoverable(pvMark)}}var showsInteraction=def.get(keyArgs,'showsInteraction');if(showsInteraction!=null){if(showsInteraction){bits|=this._bitShowsInteraction}else{bits&=~this._bitShowsInteraction}}var showsActivity=def.get(keyArgs,'showsActivity');if(showsActivity!=null){if(showsActivity){bits|=this._bitShowsActivity}else{bits&=~this._bitShowsActivity}}var showsSelection=def.get(keyArgs,'showsSelection');if(showsSelection!=null){if(showsSelection){bits|=this._bitShowsSelection}else{bits&=~this._bitShowsSelection}}if(!def.get(keyArgs,'noClick')&&panel._isClickable()){bits|=this._bitClickable;clickable=true}if(clickSelectable||clickable){panel._addPropClick(pvMark)}if(!def.get(keyArgs,'noDoubleClick')&&panel._isDoubleClickable()){bits|=this._bitDoubleClickable;panel._addPropDoubleClick(pvMark)}this.bits=bits},fillColor:function(){return this.color('fill')},strokeColor:function(){return this.color('stroke')},defaultColor:function(){return this.defaultColorSceneScale()(this.scene)},dimColor:function(color){return pvc.toGrayScale(color,-0.3,null,null)},_initDefaultColorSceneScale:function(){var colorAxis=this.panel.axes.color;return colorAxis?colorAxis.sceneScale({nullToZero:false}):def.fun.constant(pvc.defaultColor)},defaultColorSceneScale:function(){return this._defaultColorSceneScale||(this._defaultColorSceneScale=this._initDefaultColorSceneScale())}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/SizeAxis.js b/pacotes/ccc2/compacto/SizeAxis.js deleted file mode 100755 index 4f1d540..0000000 --- a/pacotes/ccc2/compacto/SizeAxis.js +++ /dev/null @@ -1 +0,0 @@ -var sizeAxis_optionsDef;def.scope(function(){def.type('pvc.visual.SizeAxis',pvc.visual.Axis).init(function(chart,type,index,keyArgs){keyArgs=def.set(keyArgs,'byNaked',false);this.base(chart,type,index,keyArgs)}).add({scaleTreatsNullAs:function(){return'min'},scaleUsesAbs:function(){return this.option('UseAbs')},setScaleRange:function(range){var scale=this.scale;scale.min=range.min;scale.max=range.max;scale.size=range.max-range.min;scale.range(scale.min,scale.max);if(pvc.debug>=4){pvc.log("Scale: "+pvc.stringify(def.copyOwn(scale)))}return this},_getOptionsDefinition:function(){return sizeAxis_optionsDef}});sizeAxis_optionsDef=def.create(axis_optionsDef,{OriginIsZero:{resolve:'_resolveFull',cast:Boolean,value:false},FixedMin:{resolve:'_resolveFull',cast:pvc.castNumber},FixedMax:{resolve:'_resolveFull',cast:pvc.castNumber},UseAbs:{resolve:'_resolveFull',cast:Boolean,value:false}})}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/TranslationOper.js b/pacotes/ccc2/compacto/TranslationOper.js deleted file mode 100755 index 7ba2d2c..0000000 --- a/pacotes/ccc2/compacto/TranslationOper.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.data.TranslationOper').init(function(chart,complexTypeProj,source,metadata,options){this.chart=chart;this.complexTypeProj=complexTypeProj;this.source=source;this.metadata=metadata||{};this.options=options||{};this._initType();if(pvc.debug>=4){this._logItems=true;this._logItemCount=0}}).add({_logItems:false,logSource:def.method({isAbstract:true}),virtualItemSize:function(){return this.metadata.length},freeVirtualItemSize:function(){return this.virtualItemSize()-this._userUsedIndexesCount},defReader:function(dimReaderSpec){dimReaderSpec||def.fail.argumentRequired('readerSpec');var dimNames;if(typeof dimReaderSpec==='string'){dimNames=dimReaderSpec}else{dimNames=dimReaderSpec.names}if(typeof dimNames==='string'){dimNames=dimNames.split(/\s*\,\s*/)}else{dimNames=def.array.as(dimNames)}var indexes=def.array.as(dimReaderSpec.indexes);if(indexes){indexes.forEach(this._userUseIndex,this)}var hasDims=!!(dimNames&&dimNames.length);var reader=dimReaderSpec.reader;if(!reader){if(hasDims){return this._userCreateReaders(dimNames,indexes)}}else{hasDims||def.fail.argumentRequired('reader.names',"Required argument when a reader function is specified.");this._userRead(reader,dimNames)}return indexes},configureType:function(){this._configureTypeCore()},_configureTypeCore:def.method({isAbstract:true}),_initType:function(){this._userDimsReaders=[];this._userDimsReadersByDim={};this._userItem=[];this._userUsedIndexes={};this._userUsedIndexesCount=0;var userDimReaders=this.options.readers;if(userDimReaders){userDimReaders.forEach(this.defReader,this)}var multiChartIndexes=pvc.parseDistinctIndexArray(this.options.multiChartIndexes);if(multiChartIndexes){this._multiChartIndexes=this.defReader({names:'multiChart',indexes:multiChartIndexes})}},_userUseIndex:function(index){index=+index;(index>=0)||def.fail.argumentInvalid('index',"Invalid reader index: '{0}'.",[index]);!def.hasOwn(this._userUsedIndexes,index)||def.fail.argumentInvalid('index',"Virtual item index '{0}' is already assigned.",[index]);this._userUsedIndexes[index]=true;this._userUsedIndexesCount++;this._userItem[index]=true;return index},_userCreateReaders:function(dimNames,indexes){if(!indexes){indexes=[]}else{indexes.forEach(function(index,j){indexes[j]=+index})}var I=indexes.length,N=dimNames.length,dimName;if(N>I){var nextIndex=I>0?(indexes[I-1]+1):0;do{nextIndex=this._nextAvailableItemIndex(nextIndex);indexes[I]=nextIndex;this._userUseIndex(nextIndex);I++}while(N>I)}var L=(I===N)?N:(N-1);for(var n=0;n read: '+pvc.stringify(atoms))}return valuesByDimName},_propGet:function(dimName,prop){function propGet(item,atoms){atoms[dimName]=item[prop]}return propGet},_constGet:function(dimName,constRawValue,keyArgs){var me=this,constAtom;function constGet(item,atoms){atoms[dimName]=constAtom||(constAtom=me.data.dimensions(dimName).intern(constRawValue))}return constGet},_nextAvailableItemIndex:function(index,L){if(index==null){index=0}if(L==null){L=Infinity}while(index=2)||def.assert("Must have at least one interpolation point.");this._middleIndex=~~(stepCount/2); var dotCount=(stepCount-1);this._isOdd=(dotCount%2)>0}else{var fromCat=+last.catInfo.value;var toCat=+next.catInfo.value;this._middleCat=(toCat+fromCat)/2}}},_interpolate:function(catSerInfo){this._initInterpData();var next=this.__nextNonNull;var last=this.__lastNonNull;var one=next||last;if(!one){return}var group;var interpolation=this.interpolation;var catInfo=catSerInfo.catInfo;if(next&&last){if(interpolation._isCatDiscrete){var groupIndex=(catInfo.index-last.catInfo.index);if(this._isOdd){group=groupIndex=col.length){col.push(child)}else{col.splice(index,0,child)}}function data_removeColChild(parent,childrenProp,child,parentProp){(child&&(!child[parentProp]||child[parentProp]===parent))||def.assert("Not a child");var children=parent[childrenProp];if(children){var index=children.indexOf(child);if(index>=0){def.array.removeAt(children,index)}}child[parentProp]=null} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/def.js b/pacotes/ccc2/compacto/def.js deleted file mode 100755 index e9f5b16..0000000 --- a/pacotes/ccc2/compacto/def.js +++ /dev/null @@ -1 +0,0 @@ -var arraySlice=Array.prototype.slice;if(!Object.keys){Object.keys=function(o){if(o!==Object(o)){throw new TypeError('Object.keys called on non-object')}var ret=[];for(var p in o){if(Object.prototype.hasOwnProperty.call(o,p)){ret.push(p)}}return ret}}if(!Object.create){Object.create=(function(){var Klass=function(){},proto=Klass.prototype;function create(baseProto){Klass.prototype=baseProto||{};var instance=new Klass();Klass.prototype=proto;return instance}return create}())}if(!Function.prototype.bind){Function.prototype.bind=function(ctx){var staticArgs=arraySlice.call(arguments,1);var fToBind=this;return function(){return fToBind.apply(ctx,staticArgs.concat(arraySlice.call(arguments)))}}}if(!this.JSON){this.JSON={}}if(!this.JSON.stringify){this.JSON.stringify=function(t){return''+t}}var objectHasOwn=Object.prototype.hasOwnProperty;var def={global:this,get:function(o,p,dv){var v;return o&&(v=o[p])!=null?v:dv},gets:function(o,props){return props.map(function(p){return o[p]})},getPath:function(o,path,dv,create){if(!o){return dv}if(path!=null){var parts=def.array.is(path)?path:path.split('.');var L=parts.length;if(L){var i=0;while(i=2){to=a||{};from=b}else{to={};from=a}if(from){for(var p in from){if(objectHasOwn.call(from,p)){to[p]=from[p]}}}return to},copy:function(a,b){var to,from;if(arguments.length>=2){to=a||{};from=b}else{to={};from=a}if(from){for(var p in from){to[p]=from[p]}}return to},copyProps:function(a,b,props){var to,from;if(arguments.length>=3){to=a||{};from=b}else{to={};from=a;props=b}if(props){if(from){props.forEach(function(p){to[p]=from[p]})}else{props.forEach(function(p){to[p]=undefined})}}return to},keys:function(o){var keys=[];for(var p in o){keys.push(p)}return keys},values:function(o){var values=[];for(var p in o){values.push(o[p])}return values},uniqueIndex:function(o,key,ctx){var index={};for(var p in o){var v=key?key.call(ctx,o[p]):o[p];if(v!=null&&!objectHasOwn.call(index,v)){index[v]=p}}return index},ownKeys:Object.keys,own:function(o,f,ctx){var keys=Object.keys(o);return f?keys.map(function(key){return f.call(ctx,o[key],key)}):keys.map(function(key){return o[key]})},scope:function(scopeFun,ctx){return scopeFun.call(ctx)},compare:function(a,b){return(a===b)?0:((a>b)?1:-1)},compareReverse:function(a,b){return(a===b)?0:((a>b)?-1:1)},methodCaller:function(p,context){if(context){return function(){return context[p].apply(context,arguments)}}return function(){return this[p].apply(this,arguments)}},identity:function(x){return x},add:function(a,b){return a+b},negate:function(f){return function(){return!f.apply(this,arguments)}},noop:function noop(){},retTrue:function(){return true},retFalse:function(){return false},number:{is:function(v){return typeof v==='number'},as:function(d,dv){var v=parseFloat(d);return isNaN(v)?(dv||0):v},to:function(d,dv){var v=parseFloat(d);return isNaN(v)?(dv||0):v}},array:{is:function(v){return(v instanceof Array)},isLike:function(v){return v&&(v.length!=null)&&(typeof v!=='string')},as:function(thing){return(thing instanceof Array)?thing:((thing!=null)?[thing]:null)},to:function(thing){return(thing instanceof Array)?thing:((thing!=null)?[thing]:null)},lazy:function(scope,p,f,ctx){return scope[p]||(scope[p]=(f?f.call(ctx,p):[]))},copy:function(al){return arraySlice.apply(al,arraySlice.call(arguments,1))}},object:{is:function(v){return v&&typeof(v)==='object'},isNative:function(v){return(!!v)&&v.constructor===Object},as:function(v){return v&&typeof(v)==='object'?v:null},asNative:function(v){return v&&v.constructor===Object?v:null},lazy:function(scope,p,f,ctx){return scope[p]||(scope[p]=(f?f.call(ctx,p):{}))}},string:{is:function(v){return typeof v==='string'},to:function(v,ds){return v!=null?(''+v):(ds||'')},join:function(sep){var a=arguments;var L=a.length;var v,v2;switch(L){case 3:v=a[1];v2=a[2];if(v!=null&&v!==""){if(v2!=null&&v2!==""){return(""+v)+sep+(""+v2)}return(""+v)}else if(v2!=null&&v2!==""){return(""+v2)}return"";case 2:v=a[1];return v!=null?(""+v):"";case 1:case 0:return""}var args=[];for(var i=1;i0){mixins.unshift(instance);def.mixin.apply(def,mixins)}return instance};def.scope(function(){var shared=def.shared();function typeLocked(){return def.error.operationInvalid("Type is locked.")}var typeProto={init:function(init){init||def.fail.argumentRequired('init');var state=shared(this.safe);!state.locked||def.fail(typeLocked());var baseInit=state.init;if(baseInit){init=override(init,baseInit)}state.init=init;state.initOrPost=true;return this},postInit:function(postInit){postInit||def.fail.argumentRequired('postInit');var state=shared(this.safe);!state.locked||def.fail(typeLocked());var basePostInit=state.post;if(basePostInit){postInit=override(postInit,basePostInit)}state.post=postInit;state.initOrPost=true;return this},add:function(mixin){var state=shared(this.safe);!state.locked||def.fail(typeLocked());var proto=this.prototype;var baseState=state.base;def.each(mixin.prototype||mixin,function(value,p){switch(p){case'base':case'constructor':return;case'toString':if(value===toStringMethod){return}break;case'override':if(value===overrideMethod){return}break}if(value){var method=asMethod(value);if(method){var baseMethod;var bm=state.methods[p];if(bm&&(bm instanceof Method)){baseMethod=bm}else if(baseState){bm=baseState.methods[p];if(bm&&(bm instanceof Method)){baseMethod=bm}}state.methods[p]=method;if(baseMethod){value=baseMethod.override(method)}proto[p]=value;return}}mixinProp(proto,p,value,def.identity)});return this},getStatic:function(p){return getStatic(shared(this.safe),p)},addStatic:function(mixin){var state=shared(this.safe);!state.locked||def.fail(typeLocked());for(var p in mixin){if(p!=='prototype'){var v1=def.getOwn(this,p);var v2=mixin[p];var o2=def.object.as(v2);if(o2){var v1Local=(v1!==undefined);if(!v1Local){v1=getStatic(state.base,p)}var o1=def.object.asNative(v1);if(o1){if(v1Local){def.mixin(v1,v2);continue}v2=def.create(v1,v2)}}this[p]=v2}}return this}};function getStatic(state,p){if(state){do{var v=def.getOwn(state.constructor,p);if(v!==undefined){return v}}while((state=state.base))}}function TypeName(full){var parts;if(full){if(full instanceof Array){parts=full;full=parts.join('.')}else{parts=full.split('.')}}if(parts&&parts.length>1){this.name=parts.pop();this.namespace=parts.join('.');this.namespaceParts=parts}else{this.name=full||null;this.namespace=null;this.namespaceParts=[]}}TypeName.prototype.toString=function(){return def.string.join('.',this.namespace+'.'+this.name)};function Method(spec){this.fun=spec.as;if(spec){if(spec.isAbstract){this.isAbstract=true}}}def.copyOwn(Method.prototype,{isAbstract:false,override:function(method){if(this.isAbstract){return method.fun}var fun2=override(method.fun,this.fun);method.fun=fun2;return fun2}});function asMethod(fun){if(fun){if(def.fun.is(fun)){return new Method({as:fun})}if(fun instanceof Method){return fun}if(def.fun.is(fun.as)){return new Method(fun)}if(fun.isAbstract){return new Method({isAbstract:true,as:def.fail.notImplemented})}}return null}function method(fun){return asMethod(fun)||def.fail.argumentInvalid('fun')}function rootType(){}var rootProto=rootType.prototype;rootProto.base=undefined;var rootState={locked:true,init:undefined,postInit:undefined,initOrPost:false,methods:{},constructor:rootType};rootType.safe=shared.safe(rootState);function override(method,base){return function(){var prevBase=rootProto.base;rootProto.base=base;try{return method.apply(this,arguments)}finally{rootProto.base=prevBase}}}function overrideMethod(mname,method){this[mname]=override(method,this[mname]);return this}function toStringMethod(){return''+this.constructor}function inherits(type,base){var proto=type.prototype=Object.create(base.prototype);proto.constructor=type;return proto}function createConstructor(state){var S=1;var steps=[function(){S=0;if(state.initOrPost){steps.length=0;if(state.init){steps.push(state.init);S++}if(state.post){steps.push(state.post);S++}constructor.apply(this,arguments);return false}else{steps=null}}];function constructor(){if(S){var i=0;while(steps[i].apply(this,arguments)!==false&&++i=0?new Array(len):[];if(dv!==undefined){for(var i=0;i1){var t=target.length;for(var s=1;s>1;var result=comparer(item,key?key(array[mid]):array[mid]);if(result<0){high=mid-1}else if(result>0){low=mid+1}else{return mid}}return~low},insert:function(array,item,comparer){var index=def.array.binarySearch(array,item,comparer);if(index<0){array.splice(~index,0,item)}return index},remove:function(array,item,comparer){var index=def.array.binarySearch(array,item,comparer);if(index>=0){return array.splice(index,1)[0]}}});var nextGlobalId=1,nextIdByScope={};def.nextId=function(scope){if(scope){var nextId=def.getOwn(nextIdByScope,scope)||1;nextIdByScope[scope]=nextId+1;return nextId}return nextGlobalId++};def.type('Set').init(function(source,count){this.source=source||{};this.count=source?(count!=null?count:def.ownKeys(source).length):0}).add({has:function(p){return objectHasOwn.call(this.source,p)},add:function(p){var source=this.source;if(!objectHasOwn.call(source,p)){this.count++;source[p]=true}return this},rem:function(p){if(objectHasOwn.call(this.source,p)){delete this.source[p];this.count--}return this},clear:function(){if(this.count){this.source={};this.count=0}return this},members:function(){return def.ownKeys(this.source)}});def.type('Map').init(function(source,count){this.source=source||{};this.count=source?(count!=null?count:def.ownKeys(source).length):0}).add({has:function(p){return objectHasOwn.call(this.source,p)},get:function(p){return objectHasOwn.call(this.source,p)?this.source[p]:undefined},set:function(p,v){var source=this.source;if(!objectHasOwn.call(source,p)){this.count++}source[p]=v;return this},rem:function(p){if(objectHasOwn.call(this.source,p)){delete this.source[p];this.count--}return this},clear:function(){if(this.count){this.source={};this.count=0}return this},copy:function(other){def.eachOwn(other.source,function(value,p){this.set(p,value)},this)},values:function(){return def.own(this.source)},keys:function(){return def.ownKeys(this.source)},clone:function(){return new def.Map(def.copy(this.source),this.count)},symmetricDifference:function(other){if(!this.count){return other.clone()}if(!other.count){return this.clone()}var result={};var count=0;var as=this.source;var bs=other.source;def.eachOwn(as,function(a,p){if(!objectHasOwn.call(bs,p)){result[p]=a;count++}});def.eachOwn(bs,function(b,p){if(!objectHasOwn.call(as,p)){result[p]=b;count++}});return new def.Map(result,count)},intersect:function(other,result){if(!result){result=new def.Map()}def.eachOwn(this.source,function(value,p){if(other.has(p)){result.set(p,value)}});return result}});def.type('OrderedMap').init(function(){this._list=[];this._map={}}).add({has:function(key){return objectHasOwn.call(this._map,key)},count:function(){return this._list.length},get:function(key){var bucket=def.getOwn(this._map,key);if(bucket){return bucket.value}},at:function(index){var bucket=this._list[index];if(bucket){return bucket.value}},add:function(key,v,index){var map=this._map;var bucket=def.getOwn(map,key);if(!bucket){bucket=map[key]={key:key,value:v};if(index==null){this._list.push(bucket)}else{def.array.insertAt(this._list,index,bucket)}}else if(bucket.value!==v){bucket.value=v}return this},rem:function(key){var bucket=def.getOwn(this._map,key);if(bucket){var index=this._list.indexOf(bucket);this._list.splice(index,1);delete this._map[key]}return this},clear:function(){if(this._list.length){this._map={};this._list.length=0}return this},keys:function(){return def.ownKeys(this._map)},forEach:function(fun,ctx){return this._list.forEach(function(bucket){fun.call(ctx,bucket.value,bucket.key)})}});def.html={escape:function(str){return def.string.to(str).replace(/&/gm,"&").replace(//gm,">").replace(/"/gm,""")}};def.type('Query').init(function(){this.index=-1;this.item=undefined}).add({next:function(){var index=this.index;if(index===-2){return false}index++;if(!this._next(index)){this.index=-2;this.item=undefined;return false}this.index=index;return true},_next:def.method({isAbstract:true}),_finish:function(){this.index=-2;this.item=undefined},each:function(fun,ctx){while(this.next()){if(fun.call(ctx,this.item,this.index)===false){return true}}return false},array:function(){var array=[];while(this.next()){array.push(this.item)}return array},sort:function(compare,by){if(!compare){compare=def.compare}if(by){var keyCompare=compare;compare=function(a,b){return keyCompare(by(a),by(b))}}var sorted=this.array().sort(compare);return new def.ArrayLikeQuery(sorted)},object:function(keyArgs){var target=def.get(keyArgs,'target')||{},nameFun=def.get(keyArgs,'name'),valueFun=def.get(keyArgs,'value'),ctx=def.get(keyArgs,'context');while(this.next()){var name=''+(nameFun?nameFun.call(ctx,this.item,this.index):this.item);target[name]=valueFun?valueFun.call(ctx,this.item,this.index):this.item}return target},reduce:function(accumulator){var i=0,result;if(arguments.length<2){if(!this.next()){throw new TypeError("Length is 0 and no second argument")}result=this.item}else{result=arguments[1]}while(this.next()){result=accumulator(result,this.item,this.index);++i}return result},count:function(){var count=0;while(this.next()){count++}return count},first:function(pred,ctx,dv){while(this.next()){if(!pred||pred.call(ctx,this.item,this.index)){var item=this.item;this._finish();return item}}return dv},last:function(pred,ctx,dv){var theItem=dv;while(this.next()){if(!pred||pred.call(ctx,this.item,this.index)){theItem=this.item}}return theItem},any:function(pred,ctx){while(this.next()){if(!pred||pred.call(ctx,this.item,this.index)){this._finish();return true}}return false},all:function(pred,ctx){while(this.next()){if(!pred.call(ctx,this.item,this.index)){this._finish();return false}}return true},min:function(){var min=null;while(this.next()){if(min===null||this.itemmax){max=this.item}}return max},range:function(){var min=null,max=null;while(this.next()){var item=this.item;if(min===null){min=max=item}else{if(itemmax){max=item}}}return min!=null?{min:min,max:max}:null},multipleIndex:function(keyFun,ctx){var keyIndex={};this.each(function(item){var key=keyFun?keyFun.call(ctx,item):item;if(key!=null){var sameKeyItems=def.getOwn(keyIndex,key)||(keyIndex[key]=[]);sameKeyItems.push(item)}});return keyIndex},uniqueIndex:function(keyFun,ctx){var keyIndex={};this.each(function(item){var key=keyFun?keyFun.call(ctx,item):item;if(key!=null&&!def.hasOwn(keyIndex,key)){keyIndex[key]=item}});return keyIndex},select:function(fun,ctx){return new def.SelectQuery(this,fun,ctx)},selectMany:function(fun,ctx){return new def.SelectManyQuery(this,fun,ctx)},union:function(){var queries=def.array.append([this],arguments);return new def.SelectManyQuery(new def.ArrayLikeQuery(queries))},where:function(fun,ctx){return new def.WhereQuery(this,fun,ctx)},distinct:function(fun,ctx){return new def.DistinctQuery(this,fun,ctx)},skip:function(n){return new def.SkipQuery(this,n)},take:function(n){if(n<=0){return new def.NullQuery()}if(!isFinite(n)){return this}return new def.TakeQuery(this,n)},whayl:function(pred,ctx){return new def.WhileQuery(this,pred,ctx)},reverse:function(){return new def.ReverseQuery(this)}});def.type('NullQuery',def.Query).add({_next:function(){}});def.type('AdhocQuery',def.Query).init(function(next){this.base();this._next=next});def.type('ArrayLikeQuery',def.Query).init(function(list){this.base();this._list=def.array.isLike(list)?list:[list];this._count=this._list.length}).add({_next:function(nextIndex){var count=this._count;if(nextIndex=count){return 0}this._count--}this.item=list[nextIndex];return 1}},count:function(){var remaining=this._count;if(this.index>=0){remaining-=(this.index+1)}this._finish();return remaining}});def.type('RangeQuery',def.Query).init(function(start,count,step){this.base();this._index=start;this._count=count;this._step=step==null?1:step}).add({_next:function(nextIndex){if(nextIndex=0){remaining-=(this.index+1)}this._finish();return remaining}});def.type('WhereQuery',def.Query).init(function(source,where,ctx){this.base();this._where=where;this._ctx=ctx;this._source=source}).add({_next:function(nextIndex){var source=this._source;while(source.next()){var nextItem=source.item;if(this._where.call(this._ctx,nextItem,source.index)){this.item=nextItem;return 1}}}});def.type('WhileQuery',def.Query).init(function(source,pred,ctx){this.base();this._pred=pred;this._ctx=ctx;this._source=source}).add({_next:function(nextIndex){while(this._source.next()){var nextItem=this._source.item;if(this._pred.call(this._ctx,nextItem,this._source.index)){this.item=nextItem;return 1}return 0}}});def.type('SelectQuery',def.Query).init(function(source,select,ctx){this.base();this._select=select;this._ctx=ctx;this._source=source}).add({_next:function(nextIndex){if(this._source.next()){this.item=this._select.call(this._ctx,this._source.item,this._source.index);return 1}}});def.type('SelectManyQuery',def.Query).init(function(source,selectMany,ctx){this.base();this._selectMany=selectMany;this._ctx=ctx;this._source=source;this._manySource=null}).add({_next:function(nextIndex){while(true){if(this._manySource){if(this._manySource.next()){this.item=this._manySource.item;return 1}this._manySource=null}if(!query_nextMany.call(this)){break}}}});function query_nextMany(){while(this._source.next()){var manySource=this._selectMany?this._selectMany.call(this._ctx,this._source.item,this._source.index):this._source.item;if(manySource!=null){this._manySource=def.query(manySource);return 1}}}def.type('DistinctQuery',def.Query).init(function(source,key,ctx){this.base();this._key=key;this._ctx=ctx;this._source=source;this._keys={}}).add({_next:function(nextIndex){while(this._source.next()){var nextItem=this._source.item,keyValue=this._key?this._key.call(this._ctx,nextItem,this._source.index):nextItem;if(keyValue!=null&&!def.hasOwn(this._keys,keyValue)){this._keys[keyValue]=true;this.item=nextItem;return 1}}}});def.type('SkipQuery',def.Query).init(function(source,skip){this.base();this._source=source;this._skip=skip}).add({_next:function(nextIndex){while(this._source.next()){if(this._skip>0){this._skip--}else{this.item=this._source.item;return 1}}}});def.type('TakeQuery',def.Query).init(function(source,take){this.base();this._source=source;this._take=take}).add({_next:function(nextIndex){if(this._take>0&&this._source.next()){this._take--;this.item=this._source.item;return 1}}});def.type('ReverseQuery',def.Query).init(function(source){this.base();this._source=source}).add({_next:function(nextIndex){if(!nextIndex){if(this._source instanceof def.Query){if(this._source instanceof def.ArrayLikeQuery){this._source=this._source._list}else{this._source=this._source.array()}}this._count=this._source.length}var count=this._count;if(nextIndex>>0;for(var i=0;i=len){throw new Error("reduce: no values, no initial value")}}}for(;i=0&&j=69)&&(x<100)?1900:0)))});return"([0-9]+)"}case'%Y':{fields.push(function(x){year=x});return"([0-9]+)"}case'%%':{fields.push(function(){});return"%"}}return s});var match=s.match(re);if(match)match.forEach(function(m,i){fields[i](m)});return new Date(year,month,date,hour,minute,second)};return format};pv.Format.time=function(type){var pad=pv.Format.pad;function format(t){t=Number(t);switch(type){case"short":{if(t>=31536e6){return(t/31536e6).toFixed(1)+" years"}else if(t>=6048e5){return(t/6048e5).toFixed(1)+" weeks"}else if(t>=864e5){return(t/864e5).toFixed(1)+" days"}else if(t>=36e5){return(t/36e5).toFixed(1)+" hours"}else if(t>=6e4){return(t/6e4).toFixed(1)+" minutes"}return(t/1e3).toFixed(1)+" seconds"}case"long":{var a=[],s=((t%6e4)/1e3)>>0,m=((t%36e5)/6e4)>>0;a.push(pad("0",2,s));if(t>=36e5){var h=((t%864e5)/36e5)>>0;a.push(pad("0",2,m));if(t>=864e5){a.push(pad("0",2,h));a.push(Math.floor(t/864e5).toFixed())}else{a.push(h.toFixed())}}else{a.push(m.toFixed())}return a.reverse().join(":")}}}format.format=format;format.parse=function(s){switch(type){case"short":{var re=/([0-9,.]+)\s*([a-z]+)/g,a,t=0;while(a=re.exec(s)){var f=parseFloat(a[0].replace(",","")),u=0;switch(a[2].toLowerCase()){case"year":case"years":u=31536e6;break;case"week":case"weeks":u=6048e5;break;case"day":case"days":u=864e5;break;case"hour":case"hours":u=36e5;break;case"minute":case"minutes":u=6e4;break;case"second":case"seconds":u=1e3;break}t+=f*u}return t}case"long":{var a=s.replace(",","").split(":").reverse(),t=0;if(a.length)t+=parseFloat(a[0])*1e3;if(a.length>1)t+=parseFloat(a[1])*6e4;if(a.length>2)t+=parseFloat(a[2])*36e5;if(a.length>3)t+=parseFloat(a[3])*864e5;return t}}}return format};pv.Format.number=function(){var mini=0,maxi=Infinity,mins=0,minf=0,maxf=0,maxk=1,padi="0",padf="0",padg=true,decimal=".",group=",",np="\u2212",ns="";function format(x){if(Infinity>maxf)x=Math.round(x*maxk)/maxk;var s=String(Math.abs(x)).split(".");var i=s[0];if(i.length>maxi)i=i.substring(i.length-maxi);if(padg&&(i.length3)i=i.replace(/\B(?=(?:\d{3})+(?!\d))/g,group);if(!padg&&(i.lengthmaxf){f=s[1]=f.substr(0,maxf)}if(f.lengthmaxi)i=i.substring(i.length-maxi);var f=s[1]?Number("0."+s[1]):0;if(Infinity>maxf)f=Math.round(f*maxk)/maxk;return Math.round(i)+f};format.integerDigits=function(min,max){if(arguments.length){mini=Number(min);maxi=(arguments.length>1)?Number(max):mini;mins=mini+Math.floor(mini/3)*group.length;return this}return[mini,maxi]};format.fractionDigits=function(min,max){if(arguments.length){minf=Number(min);maxf=(arguments.length>1)?Number(max):minf;maxk=Math.pow(10,maxf);return this}return[minf,maxf]};format.integerPad=function(x){if(arguments.length){padi=String(x);padg=/\d/.test(padi);return this}return padi};format.fractionPad=function(x){if(arguments.length){padf=String(x);return this}return padf};format.decimal=function(x){if(arguments.length){decimal=String(x);return this}return decimal};format.group=function(x){if(arguments.length){group=x?String(x):"";mins=mini+Math.floor(mini/3)*group.length;return this}return group};format.negativeAffix=function(x,y){if(arguments.length){np=String(x||"");ns=String(y||"");return this}return[np,ns]};return format};(function(){var _cache;pv.Text={};pv.Text.createCache=function(){return new FontSizeCache()};pv.Text.usingCache=function(cache,fun,ctx){if(!(cache instanceof FontSizeCache)){throw new Error("Not a valid cache.")}var prevCache=_cache;_cache=cache;try{return fun.call(ctx)}finally{_cache=prevCache}};pv.Text.measure=function(text,font){if(text==null){text=""}else{text=""+text}var bbox=_cache&&_cache.get(font,text);if(!bbox){if(!text){bbox={width:0,height:0}}else{bbox=this.measureCore(text,font)}if(_cache){_cache.put(font,text,bbox)}}return bbox};pv.Text.fontHeight=function(font){return pv.Text.measure('M',font).height};pv.Text.measureCore=(function(){var _svgText,_svgTextFont;function createTextSizePlaceholder(){var div=document.createElement('div');div.id='pvSVGText_'+new Date().getTime();var style=div.style;style.position='absolute';style.visibility='hidden';style.width=0;style.height=0;style.left=0;style.top=0;document.body.appendChild(div);return div}return function(text,font){if(!_svgText){var holder=createTextSizePlaceholder();var svgElem=pv.SvgScene.create('svg');svgElem.setAttribute('font-size','10px');svgElem.setAttribute('font-family','sans-serif');_svgText=pv.SvgScene.create('text');svgElem.appendChild(_svgText);holder.appendChild(svgElem)}if(!font){font=null}if(_svgTextFont!==font){_svgTextFont=font;pv.SvgScene.setStyle(_svgText,{'font':font})}var textNode=_svgText.firstChild;if(textNode){textNode.nodeValue=''+text}else{if(pv.renderer()==="svgweb"){_svgText.appendChild(document.createTextNode(''+text,true))}else{_svgText.appendChild(document.createTextNode(''+text))}}var box=_svgText.getBBox();return{width:box.width,height:box.height}}}());var FontSizeCache=function(){this._fontsCache={}};var hasOwnProp=Object.prototype.hasOwnProperty;FontSizeCache.prototype._getFont=function(font){font=font||'';return hasOwnProp.call(this._fontsCache,font)?this._fontsCache[font]:(this._fontsCache[font]={})};FontSizeCache.prototype.get=function(font,text){text=text||'';var fontCache=this._getFont(font);return hasOwnProp.call(fontCache,text)?fontCache[text]:null};FontSizeCache.prototype.put=function(font,text,size){return this._getFont(font)[text||'']=size}}());pv.map=function(array,f){var o={};return f?array.map(function(d,i){o.index=i;return f.call(o,d)}):array.slice()};pv.repeat=function(array,n){if(arguments.length==1)n=2;return pv.blend(pv.range(n).map(function(){return array}))};pv.array=function(len,dv){var a=len>=0?new Array(len):[];if(dv!==undefined){for(var i=0;in){arrays.length=m;for(var i=n;ib)?1:0)};pv.reverseOrder=function(b,a){return(ab)?1:0)};pv.search=function(array,value,f){if(!f)f=pv.identity;var low=0,high=array.length-1;while(low<=high){var mid=(low+high)>>1,midValue=f(array[mid]);if(midValuevalue)high=mid-1;else return mid}return-low-1};pv.search.index=function(array,value,f){var i=pv.search(array,value,f);return(i<0)?(-i-1):i};pv.range=function(start,stop,step){if(arguments.length==1){stop=start;start=0}if(step==undefined)step=1;if((stop-start)/step==Infinity)throw new Error("range must be finite");var array=[],i=0,j;stop-=(stop-start)*1e-10;if(step<0){while((j=start+step*i++)>stop){array.push(j)}}else{while((j=start+step*i++)maxx){maxx=x;maxi=i}}return maxi};pv.min=function(array,f){if(f==pv.index)return 0;return Math.min.apply(null,f?pv.map(array,f):array)};pv.min.index=function(array,f){if(!array.length)return-1;if(f==pv.index)return 0;if(!f)f=pv.identity;var mini=0,minx=Infinity,o={};for(var i=0;i0)?Math.pow(b,Math.floor(pv.log(x,b))):-Math.pow(b,-Math.floor(-pv.log(-x,b)))};pv.logCeil=function(x,b){return(x>0)?Math.pow(b,Math.ceil(pv.log(x,b))):-Math.pow(b,-Math.ceil(-pv.log(-x,b)))};(function(){var radians=Math.PI/180,degrees=180/Math.PI;pv.radians=function(degrees){return radians*degrees};pv.degrees=function(radians){return degrees*radians}})();pv.keys=function(map){var array=[];for(var key in map){array.push(key)}return array};pv.entries=function(map){var array=[];for(var key in map){array.push({key:key,value:map[key]})}return array};pv.values=function(map){var array=[];for(var key in map){array.push(map[key])}return array};pv.dict=function(keys,f){var m={},o={};for(var i=0;iL){throw new Error("Index out of range.")}var ni=i+1;var firstDirtyIndex=this._firstDirtyChildIndex;if(ni=nn*31536e6){precision=31536e6;format="%Y";increment=function(d){d.setFullYear(d.getFullYear()+step)}}else if(span>=nn*2592e6){precision=2592e6;format="%m/%Y";increment=function(d){d.setMonth(d.getMonth()+step)}}else if(span>=nn*6048e5){precision=6048e5;format="%m/%d";increment=function(d){d.setDate(d.getDate()+7*step)}}else if(span>=nn*864e5){precision=864e5;format="%m/%d";increment=function(d){d.setDate(d.getDate()+step)}}else if(span>=nn*36e5){precision=36e5;format="%I:%M %p";increment=function(d){d.setHours(d.getHours()+step)}}else if(span>=nn*6e4){precision=6e4;format="%I:%M %p";increment=function(d){d.setMinutes(d.getMinutes()+step)}}else if(span>=nn*1e3){precision=1e3;format="%I:%M:%S";increment=function(d){d.setSeconds(d.getSeconds()+step)}}else{precision=1;format="%S.%Qs";increment=function(d){d.setTime(d.getTime()+step)}}precision=dateTickPrecision?dateTickPrecision:precision;format=dateTickFormat?dateTickFormat:format;usedDateTickPrecision=precision;tickFormat=pv.Format.date(format);var date=new Date(min),dates=[];floor(date,precision);var n=span/precision;if(n>10){switch(precision){case 36e5:{step=(n>20)?6:3;date.setHours(Math.floor(date.getHours()/step)*step);break}case 2592e6:{step=(n>24)?3:((n>12)?2:1);date.setMonth(Math.floor(date.getMonth()/step)*step);break}case 6048e5:{step=(n>15)?3:(n>10?2:1);date.setDate(Math.floor(date.getDate()/(7*step))*(7*step));break}case 864e5:{step=(n>=30)?5:((n>=15)?3:2);date.setDate(Math.floor(date.getDate()/step)*step);break}case 6e4:{step=(n>30)?15:((n>15)?10:5);date.setMinutes(Math.floor(date.getMinutes()/step)*step);break}case 1e3:{step=(n>90)?15:((n>60)?10:5);date.setSeconds(Math.floor(date.getSeconds()/step)*step);break}case 1:{step=(n>1000)?250:((n>200)?100:((n>100)?50:((n>50)?25:5)));date.setMilliseconds(Math.floor(date.getMilliseconds()/step)*step);break}default:{step=pv.logCeil(n/15,10);if(n/step<2)step/=5;else if(n/step<5)step/=2;date.setFullYear(Math.floor(date.getFullYear()/step)*step);break}}}if(dateTickPrecision){step=1;increment=function(d){d.setSeconds(d.getSeconds()+step*dateTickPrecision/1000)}}while(true){increment(date);if(date>max)break;dates.push(new Date(date))}return reverse?dates.reverse():dates}if(m==null){m=10}var roundInside=pv.get(options,'roundInside',true);var exponentMin=pv.get(options,'numberExponentMin',-Infinity);var exponentMax=pv.get(options,'numberExponentMax',+Infinity);var exponent=Math.floor(pv.log(span/m,10));var overflow=false;if(exponent>exponentMax){exponent=exponentMax;overflow=true}else if(exponent0;k--)ticks.push(-pow(-i)*k)}else{for(;id[1];j--);return ticks.slice(i,j)};scale.tickFormat=function(t){return t.toPrecision(1)};scale.nice=function(){var d=scale.domain();return scale.domain(pv.logFloor(d[0],b),pv.logCeil(d[1],b))};scale.base=function(v){if(arguments.length){b=Number(v);p=Math.log(b);scale.transform(log,pow);return this}return b};scale.domain.apply(scale,arguments);return scale.base(10)};pv.Scale.root=function(){var scale=pv.Scale.quantitative();scale.power=function(v){if(arguments.length){var b=Number(v),p=1/b;scale.transform(function(x){return Math.pow(x,p)},function(y){return Math.pow(y,b)});return this}return b};scale.domain.apply(scale,arguments);return scale.power(2)};pv.Scale.ordinal=function(){var d=[],i={},r=[],band=0;function scale(x){if(!(x in i))i[x]=d.push(x)-1;return r[i[x]%r.length]}scale.domain=function(array,f){if(arguments.length){array=(array instanceof Array)?((arguments.length>1)?pv.map(array,f):array):Array.prototype.slice.call(arguments);d=[];var seen={};for(var j=0;j1)?pv.map(array,f):array):Array.prototype.slice.call(arguments);if(typeof r[0]=="string")r=r.map(pv.color);r.min=r[0];r.max=r[r.length-1];return this}return r};scale.split=function(min,max){var R=max-min;var N=this.domain().length;var step=0;if(R===0){r=pv.array(N,min)}else if(N){step=(max-min)/N;r=pv.range(min+step/2,max,step)}r.min=min;r.max=max;r.step=step;return this};scale.splitBandedCenter=function(min,max,band){scale.split(min,max);if(band==null){band=1}r.band=r.step*band;r.margin=r.step-r.band;r.min=min;r.max=max;return this};scale.splitBandedFlushCenter=function(min,max,band){if(band==null){band=1}var R=(max-min),N=this.domain().length,S=0,B=0,M=0;if(R===0){r=pv.array(N,min)}else if(N){B=(R*band)/N;M=N>1?((R-N*B)/(N-1)):0;S=M+B;r=pv.range(min+B/2,max,S)}r.step=S;r.band=B;r.margin=M;r.min=min;r.max=max;return this};scale.splitFlush=function(min,max){var n=this.domain().length,step=(max-min)/(n-1);r=(n==1)?[(min+max)/2]:pv.range(min,max+step/2,step);r.min=min;r.max=max;return this};scale.splitBanded=function(min,max,band){if(arguments.length<3)band=1;if(band<0){var n=this.domain().length,total=-band*n,remaining=max-min-total,padding=remaining/(n+1);r=pv.range(min+padding,max,padding-band);r.band=-band}else{var step=(max-min)/(this.domain().length+(1-band));r=pv.range(min+step*(1-band),max,step);r.band=step*band;r.step=step;r.margin=step-r.band}r.min=min;r.max=max;return this};scale.invertIndex=function(y,noRound){var N=this.domain().length;if(N===0){return-1}var r=this.range();var R=r.max-r.min;if(R===0){return 0}var S=R/N;if(y>=r.max){return N}if(y=rect.x)&&(this.x<=rect.x2)&&(this.y>=rect.y)&&(this.y<=rect.y2)};pv.Vector.prototype.containsPoint=function(p){return(this.x===p.x)&&(this.y===p.y)};pv.Vector.prototype.points=function(){return[this]};pv.Vector.prototype.edges=function(){return[]};pv.Vector.prototype.center=function(){return this};pv.Vector.prototype.distance2=function(p,k){return dist2(this,p,k)}}());(function(){var Point=pv.Shape.Point;var dist2=pv.Shape.dist2;pv.Shape.Line=function(x,y,x2,y2){this.x=x||0;this.y=y||0;this.x2=x2||0;this.y2=y2||0};var Line=pv.Shape.Line;Line.prototype=pv.extend(pv.Shape);Line.prototype.hasArea=function(){return false};Line.prototype.clone=function(){return new Line(this.x,this.y,this.x2,this.x2)};Line.prototype.apply=function(t){var x=t.x+(t.k*this.x);var y=t.y+(t.k*this.y);var x2=t.x+(t.k*this.x2);var y2=t.y+(t.k*this.y2);return new Line(x,y,x2,y2)};Line.prototype.points=function(){return[new Point(this.x,this.y),new Point(this.x2,this.y2)]};Line.prototype.edges=function(){return[this]};Line.prototype.center=function(){return new Point((this.x+this.x2)/2,(this.y+this.y2)/2)};Line.prototype.normal=function(at,shapeCenter){var points=this.points();var norm=points[1].minus(points[0]).perp().norm();if(shapeCenter){var outside=points[0].minus(shapeCenter);if(outside.dot(norm)<0){norm=norm.times(-1)}}return norm};Line.prototype.intersectsRect=function(rect){var i,L;var points=this.points();L=points.length;for(i=0;i1){return false}var ub=numb/denom;if(ub<0||ub>1){return false}return true};Line.prototype.distance2=function(p,k){var v=this;var w={x:this.x2,y:this.y2};var l2=dist2(v,w).dist2;if(l2<=1e-10){return dist2(p,v,k)}var wvx=w.x-v.x;var wvy=w.y-v.y;var t=((p.x-v.x)*wvx+(p.y-v.y)*wvy)/l2;if(t<0){return dist2(p,v,k)}if(t>1){return dist2(p,w,k)}var proj={x:v.x+t*wvx,y:v.y+t*wvy};return dist2(p,proj,k)}}());(function(){var Point=pv.Shape.Point;var Line=pv.Shape.Line;pv.Shape.Polygon=function(points){this._points=points||[]};var Polygon=pv.Shape.Polygon;Polygon.prototype=pv.extend(pv.Shape);Polygon.prototype.points=function(){return this._points};Polygon.prototype.clone=function(){return new Polygon(this.points().slice())};Polygon.prototype.apply=function(t){var points=this.points();var L=points.length;var points2=new Array(L);for(var i=0;i2){edges.push(new Line(point.x,point.y,firstPoint.x,firstPoint.y))}}}return edges};Polygon.prototype.distance2=function(p,k){var min={cost:Infinity,dist2:Infinity};this.edges().forEach(function(edge){var d=edge.distance2(p,k);if(d.costmax.x){max.x=point.x}if(point.y>max.y){max.y=point.y}}});if(min){bbox=this._bbox=new pv.Shape.Rect(min.x,min.y,max.x-min.x,max.y-min.y)}}return bbox}}());(function(){var Point=pv.Shape.Point;var Line=pv.Shape.Line;pv.Shape.Rect=function(x,y,dx,dy){this.x=x||0;this.y=y||0;this.dx=dx||0;this.dy=dy||0;if(this.dx<0){this.dx=-this.dx;this.x=this.x-this.dx}if(this.dy<0){this.dy=-this.dy;this.y=this.y-this.dy}this.x2=this.x+this.dx;this.y2=this.y+this.dy};var Rect=pv.Shape.Rect;Rect.prototype=pv.extend(pv.Shape.Polygon);Rect.prototype.clone=function(){var r2=Object.create(Rect.prototype);r2.x=this.x;r2.y=this.y;r2.dx=this.dx;r2.dy=this.dy;r2.x2=this.x2;r2.y2=this.y2;return r2};Rect.prototype.apply=function(t){var x=t.x+(t.k*this.x);var y=t.y+(t.k*this.y);var dx=t.k*this.dx;var dy=t.k*this.dy;return new Rect(x,y,dx,dy)};Rect.prototype.containsPoint=function(p){return this.x<=p.x&&p.x<=this.x2&&this.y<=p.y&&p.y<=this.y2};Rect.prototype.intersectsRect=function(rect){return(this.x2>rect.x)&&(this.xrect.y)&&(this.ydx2+r)||(circleDistY>dy2+r)){return false}if(circleDistX<=dx2||circleDistY<=dy2){return true}var sqCornerDistance=pow(circleDistX-dx2,2)+pow(circleDistY-dy2,2);return sqCornerDistance<=r*r};Circle.prototype.intersectLine=function(line,isInfiniteLine){var baX=line.x2-line.x;var baY=line.y2-line.y;var caX=this.x-line.x;var caY=this.y-line.y;var ba2=baX*baX+baY*baY;var bBy2=baX*caX+baY*caY;var r=this.radius;var c=caX*caX+caY*caY-r*r;var pBy2=bBy2/ba2;var disc=pBy2*pBy2-c/ba2;if(disc<0){return}var discSqrt=sqrt(disc);var t1=pBy2-discSqrt;var t2=pBy2+discSqrt;var ps=[];if(isInfiniteLine||(t1>=0&&t1<=1)){ps.push(new Point(line.x+baX*t1,line.y+baY*t1))}if(disc!==0){if(isInfiniteLine||(t2>=0&&t2<=1)){ps.push(new Point(line.x+baX*t2,line.y+baY*t2))}}return ps};Circle.prototype.points=function(){return[this.center()]};Circle.prototype.center=function(){return new Point(this.x,this.y)};Circle.prototype.normal=function(at){return at.minus(this.x,this.y).norm()};Circle.prototype.containsPoint=function(p){var dx=p.x-this.x,dy=p.y-this.y,r=this.radius;return dx*dx+dy*dy<=r*r};Circle.prototype.distance2=function(p,k){var dx=p.x-this.x,dy=p.y-this.y,r=this.radius;var b=p.minus(this).norm().times(r).plus(this);var dBorder=dist2(p,b,k);return dBorder}}());(function(){var Point=pv.Shape.Point;var dist2=pv.Shape.dist2;var normalizeAngle=pv.Shape.normalizeAngle;var atan2Norm=pv.Shape.atan2Norm;var cos=Math.cos;var sin=Math.sin;var sqrt=Math.sqrt;pv.Shape.Arc=function(x,y,radius,startAngle,angleSpan){this.x=x;this.y=y;this.radius=radius;this.startAngle=normalizeAngle(startAngle);this.angleSpan=normalizeAngle(angleSpan);this.endAngle=this.startAngle+this.angleSpan};var Arc=pv.Shape.Arc;Arc.prototype=pv.extend(pv.Shape);Arc.prototype.hasArea=function(){return false};Arc.prototype.clone=function(){var arc=Object.create(Arc.prototype);var me=this;arc.x=me.x;arc.y=me.y;arc.radius=me.radius;arc.startAngle=me.startAngle;arc.angleSpan=me.angleSpan;arc.endAngle=me.endAngle;return arc};Arc.prototype.apply=function(t){var x=t.x+(t.k*this.x);var y=t.y+(t.k*this.y);var r=t.k*this.radius;return new Arc(x,y,r,this.startAngle,this.angleSpan)};Arc.prototype.containsPoint=function(p){var dx=p.x-this.x;var dy=p.y-this.y;var r=sqrt(dx*dx+dy*dy);if(Math.abs(r-this.radius)<=1e-10){var a=atan2Norm(dy,dx);return this.startAngle<=a&&a<=this.endAngle}return false};Arc.prototype.intersectsRect=function(rect){var i,L;var points=this.points();var L=points.length;for(i=0;i=this.innerRadius&&r<=this.outerRadius){var a=atan2Norm(dy,dx);return this.startAngle<=a&&a<=this.endAngle}return false};Wedge.prototype.intersectsRect=function(rect){var i,L;var points=this.points();L=points.length;for(i=0;i0){pii=new Point(x+ir*cai,y+ir*sai);pfi=new Point(x+ir*caf,y+ir*saf)}else{pii=pfi=new Point(x,y)}var pio=new Point(x+or*cai,y+or*sai);var pfo=new Point(x+or*caf,y+or*saf);edges=this._edges=[];if(ir>0){edges.push(new Arc(x,y,ir,ai,aa))}edges.push(new Line(pii.x,pii.y,pio.x,pio.y),new Arc(x,y,or,ai,aa),new Line(pfi.x,pfi.y,pfo.x,pfo.y));var points=this._points=[pii,pio,pfo];if(ir>0){points.push(pfi)}}return edges};Wedge.prototype.distance2=function(p,k){var min={cost:Infinity,dist2:Infinity};this.edges().forEach(function(edge){var d=edge.distance2(p,k);if(d.cost0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g360)h-=360;else if(h<0)h+=360;if(h<60)return m1+(m2-m1)*h/60;if(h<180)return m2;if(h<240)return m1+(m2-m1)*(240-h)/60;return m1}function vv(h){return Math.round(v(h)*255)}return pv.rgb(vv(h+120),vv(h),vv(h-120),this.a)};pv.Color.names={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32",transparent:pv.Color.transparent=pv.rgb(0,0,0,0)};(function(){var names=pv.Color.names;names.none=names.transparent;for(var name in names)names[name]=pv.color(names[name])})();pv.colors=function(){var scale=pv.Scale.ordinal();scale.range.apply(scale,arguments);return scale};pv.Colors={};pv.Colors.category10=function(){var scale=pv.colors("#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf");scale.domain.apply(scale,arguments);return scale};pv.Colors.category20=function(){var scale=pv.colors("#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5");scale.domain.apply(scale,arguments);return scale};pv.Colors.category19=function(){var scale=pv.colors("#9c9ede","#7375b5","#4a5584","#cedb9c","#b5cf6b","#8ca252","#637939","#e7cb94","#e7ba52","#bd9e39","#8c6d31","#e7969c","#d6616b","#ad494a","#843c39","#de9ed6","#ce6dbd","#a55194","#7b4173");scale.domain.apply(scale,arguments);return scale};(function(){pv.fillStyle=function(format){if(format.type){return format}if(format.rgb){return new pv.FillStyle.Solid(format.color,format.opacity)}var match=/^\s*([a-z\-]+)\(\s*(.*?)\s*\)\s*$/.exec(format);if(match){switch(match[1]){case"linear-gradient":return parseLinearGradient(match[2]);case"radial-gradient":return parseRadialGradient(match[2])}}return new pv.FillStyle.Solid(pv.color(format))};var keyAnglesDeg={top:0,'top right':45,right:90,'bottom right':135,bottom:180,'bottom left':225,left:270,'top left':315};function parseLinearGradient(text){var terms=parseText(text);if(!terms.length){return null}var angle=Math.PI;var keyAngle;var m,f;var term=terms[0];if(term.indexOf('to ')===0){m=/^to\s+(?:((top|bottom)(?:\s+(left|right))?)|((left|right)(?:\\s+(top|bottom))?))$/.exec(term);if(m){if(m[1]){keyAngle=m[2];if(m[3]){keyAngle+=' '+m[3]}}else{keyAngle=m[5];if(m[6]){keyAngle=m[6]+' '+keyAngle}}angle=pv.radians(keyAnglesDeg[keyAngle]);terms.shift()}}else{f=parseFloat(term);if(!isNaN(f)){angle=f;if(/^.*?deg$/.test(term)){angle=pv.radians(angle)}terms.shift()}}var stops=parseStops(terms);switch(stops.length){case 0:return null;case 1:return new pv.FillStyle.Solid(stops[0].color,1)}return new pv.FillStyle.LinearGradient(angle,stops,text)}function parseRadialGradient(text){var terms=parseText(text);if(!terms.length){return null}var stops=parseStops(terms);switch(stops.length){case 0:return null;case 1:return new pv.FillStyle.Solid(stops[0].color,1)}return new pv.FillStyle.RadialGradient(50,50,stops,text)}function parseText(text){var colorFuns={};var colorFunId=0;text=text.replace(/\b\w+?\(.*?\)/g,function($0){var id='__color'+(colorFunId++);colorFuns[id]=$0;return id});var terms=text.split(/\s*,\s*/);if(!terms.length){return null}if(colorFunId){terms.forEach(function(id,index){if(colorFuns.hasOwnProperty(id)){terms[index]=colorFuns[id]}})}return terms}function parseStops(terms){var stops=[];var minOffsetPercent=+Infinity;var maxOffsetPercent=-Infinity;var pendingOffsetStops=[];function processPendingStops(lastOffset){var count=pendingOffsetStops.length;if(count){var firstOffset=maxOffsetPercent;var step=(lastOffset-firstOffset)/(count+1);for(var i=0;imaxOffsetPercent){maxOffsetPercent=offsetPercent}else if(offsetPercent=2&&(minOffsetPercent<0||maxOffsetPercent>100)){var colorDomain=[];var colorRange=[];stops.forEach(function(stop){colorDomain.push(stop.offset);colorRange.push(stop.color)});var colorScale=pv.scale.linear().domain(colorDomain).range(colorRange);if(minOffsetPercent<0){while(stops.length&&stops[0].offset<=0){stops.shift()}stops.unshift({offset:0,color:colorScale(0)})}if(maxOffsetPercent>100){while(stops.length&&stops[stops.length-1].offset>=100){stops.pop()}stops.push({offset:100,color:colorScale(100)})}}return stops}var FillStyle=pv.FillStyle=function(type){this.type=type;this.key=type};FillStyle.prototype=new pv.Color('none',1);FillStyle.prototype.rgb=function(){var color=pv.color(this.color);if(this.opacity!==color.opacity){color=color.alpha(this.opacity)}return color};var Solid=pv.FillStyle.Solid=function(color,opacity){FillStyle.call(this,'solid');if(color.rgb){this.color=color.color;this.opacity=color.opacity}else{this.color=color;this.opacity=opacity}this.key+=" "+this.color+" alpha("+this.opacity+")"};Solid.prototype=pv.extend(pv.FillStyle);Solid.prototype.alpha=function(opacity){return new Solid(this.color,opacity)};Solid.prototype.brighter=function(k){return new Solid(this.rgb().brighter(k))};Solid.prototype.darker=function(k){return new Solid(this.rgb().darker(k))};pv.FillStyle.transparent=new Solid(pv.Color.transparent);var gradient_id=0;var Gradient=pv.FillStyle.Gradient=function(type,stops){FillStyle.call(this,type);this.id=++gradient_id;this.stops=stops;if(stops.length){this.color=stops[0].color.color}this.key+=" stops("+stops.map(function(stop){var color=stop.color;return color.color+" alpha("+color.opacity+") at("+stop.offset+")"}).join(", ")+")"};Gradient.prototype=pv.extend(pv.FillStyle);Gradient.prototype.rgb=function(){return this.stops.length?this.stops[0].color:undefined};Gradient.prototype.alpha=function(opacity){return this._clone(this.stops.map(function(stop){return{offset:stop.offset,color:stop.color.alpha(opacity)}}))};Gradient.prototype.darker=function(k){return this._clone(this.stops.map(function(stop){return{offset:stop.offset,color:stop.color.darker(k)}}))};Gradient.prototype.brighter=function(k){return this._clone(this.stops.map(function(stop){return{offset:stop.offset,color:stop.color.brighter(k)}}))};var LinearGradient=pv.FillStyle.LinearGradient=function(angle,stops){Gradient.call(this,'lineargradient',stops);this.angle=angle;this.key+=" angle("+angle+")"};LinearGradient.prototype=pv.extend(Gradient);LinearGradient.prototype._clone=function(stops){return new LinearGradient(this.angle,stops)};var RadialGradient=pv.FillStyle.RadialGradient=function(cx,cy,stops){Gradient.call(this,'radialgradient',stops);this.cx=cx;this.cy=cy;this.key+=" center("+cx+","+cy+")"};RadialGradient.prototype=pv.extend(Gradient);RadialGradient.prototype._clone=function(stops){return new RadialGradient(this.cx,this.cy)}})();pv.ramp=function(start,end){var scale=pv.Scale.linear();scale.range.apply(scale,arguments);return scale};pv.Scene=pv.SvgScene={svg:"http://www.w3.org/2000/svg",xmlns:"http://www.w3.org/2000/xmlns",xlink:"http://www.w3.org/1999/xlink",xhtml:"http://www.w3.org/1999/xhtml",scale:1,events:["DOMMouseScroll","mousewheel","mousedown","mouseup","mouseover","mouseout","mousemove","click","dblclick"],implicit:{svg:{"shape-rendering":"auto","pointer-events":"painted","x":0,"y":0,"dy":0,"text-anchor":"start","transform":"translate(0,0)","fill":"none","fill-opacity":1,"stroke":"none","stroke-opacity":1,"stroke-width":1.5,"stroke-linejoin":"miter","stroke-linecap":"butt","stroke-miterlimit":8,"stroke-dasharray":"none"},css:{"font":"10px sans-serif"}}};pv.SvgScene.updateAll=function(scenes){if(scenes.length&&scenes[0].reverse&&(scenes.type!="line")&&(scenes.type!="area")){var reversed=pv.extend(scenes);for(var i=0,j=scenes.length-1;j>=0;i++,j--){reversed[i]=scenes[j]}scenes=reversed}this.removeSiblings(this[scenes.type](scenes))};pv.SvgScene.create=function(type){return document.createElementNS(this.svg,type)};pv.SvgScene.expect=function(e,type,scenes,i,attributes,style){var tagName;if(e){tagName=e.tagName;if(tagName==='defs'){e=e.nextSibling;if(e){tagName=e.tagName}}else if(tagName==='a'){e=e.firstChild}}if(e){if(tagName!==type){var n=this.create(type);e.parentNode.replaceChild(n,e);e=n}}else{e=this.create(type)}if(attributes)this.setAttributes(e,attributes);if(style)this.setStyle(e,style);return e};pv.SvgScene.setAttributes=function(e,attributes){var implicitSvg=this.implicit.svg;for(var name in attributes){var value=attributes[name];if(value==null||value==implicitSvg[name]){e.removeAttribute(name)}else{e.setAttribute(name,value)}}};pv.SvgScene.setStyle=function(e,style){var implicitCss=this.implicit.css;switch(pv.renderer()){case'batik':for(var name in style){var value=style[name];if(value==null||value==implicitCss[name]){e.removeAttribute(name)}else{e.style.setProperty(name,value)}}break;case'svgweb':for(var name in style){var value=style[name];if(value==null||value==implicitCss[name]){continue}e.style[name]=value}break;default:for(var name in style){var value=style[name];if(value==null||value==implicitCss[name]){e.style.removeProperty(name)}else{e.style[name]=value}}}};pv.SvgScene.append=function(e,scenes,index){e.$scene={scenes:scenes,index:index};e=this.title(e,scenes[index]);if(!e.parentNode)scenes.$g.appendChild(e);return e.nextSibling};pv.SvgScene.title=function(e,s){var a=e.parentNode;if(a&&(a.tagName!="a"))a=null;if(s.title){if(!a){a=this.create("a");a.setAttributeNS(this.xlink,"xlink:href","");if(e.parentNode)e.parentNode.replaceChild(a,e);a.appendChild(e)}a.setAttributeNS(this.xlink,"xlink:title",s.title);var t=null;for(var c=e.firstChild;c!=null;c=c.nextSibling){if(c.nodeName=="title"){t=c;break}}if(!t){t=this.create("title");e.appendChild(t)}else{t.removeChild(t.firstChild)}if(pv.renderer()=="svgweb"){t.appendChild(document.createTextNode(s.title,true))}else{t.appendChild(document.createTextNode(s.title))}return a}if(a)a.parentNode.replaceChild(e,a);return e};pv.SvgScene.dispatch=pv.listener(function(e){var t=e.target.$scene;if(t){var type=e.type;switch(type){case"DOMMouseScroll":type="mousewheel";e.wheel=-480*e.detail;break;case"mousewheel":e.wheel=(window.opera?12:1)*e.wheelDelta;break}if(pv.Mark.dispatch(type,t.scenes,t.index,e)){e.preventDefault()}}});pv.SvgScene.removeSiblings=function(e){while(e){var n=e.nextSibling;if(e.nodeName!=='defs'){e.parentNode.removeChild(e)}e=n}};pv.SvgScene.undefined=function(){};pv.SvgScene.removeFillStyleDefinitions=function(scenes){var results=scenes.$g.getElementsByTagName('defs');if(results.length===1){var defs;if(pv.renderer()!=="batik")defs=results[0];else defs=new cgg.element(results.item(0));var cur=defs.firstChild;while(cur){var next=cur.nextSibling;if(cur.nodeName=='linearGradient'||cur.nodeName=='radialGradient'){defs.removeChild(cur)}cur=next}}};(function(){var dashAliasMap={'-':'shortdash','.':'shortdot','-.':'shortdashdot','-..':'shortdashdotdot','. ':'dot','- ':'dash','--':'longdash','- .':'dashdot','--.':'longdashdot','--..':'longdashdotdot'};var dashMap={'shortdash':[3,1],'shortdot':[1,1],'shortdashdot':[3,1,1,1],'shortdashdotdot':[3,1,1,1,1,1],'dot':[1,3],'dash':[4,3],'longdash':[8,3],'dashdot':[4,3,1,3],'longdashdot':[8,3,1,3],'longdashdotdot':[8,3,1,3,1,3]};pv.SvgScene.isStandardDashStyle=function(dashArray){return dashMap.hasOwnProperty(dashArray)};pv.SvgScene.translateDashStyleAlias=function(dashArray){return dashAliasMap.hasOwnProperty(dashArray)?dashAliasMap[dashArray]:dashArray};pv.SvgScene.parseDasharray=function(s){var dashArray=s.strokeDasharray;if(dashArray&&dashArray!=='none'){dashArray=this.translateDashStyleAlias(dashArray);var standardDashArray=dashMap[dashArray];if(standardDashArray){dashArray=standardDashArray}else{dashArray=dashArray.split(/[\s,]+/)}var lineWidth=s.lineWidth;var lineCap=s.lineCap||'butt';var isButtCap=lineCap==='butt';dashArray=dashArray.map(function(num,index){num=+num;if(!isButtCap){if(index%2){num++}else{num-=1}}if(num<=0){num=.001}return num*lineWidth/this.scale},this).join(' ')}else{dashArray=null}return dashArray}})();(function(){var gradient_definition_id=0;function zeroRounding(x){return Math.abs(x)<=1e-12?0:x}pv.SvgScene.addFillStyleDefinition=function(scenes,fill){if(!fill.type||fill.type==='solid'){return}var isLinear=fill.type==='lineargradient';if(isLinear||fill.type==='radialgradient'){var g=scenes.$g;var results=g.getElementsByTagName('defs');var defs;if(results.length){if(pv.renderer()!=="batik")defs=results.item(0);else defs=new cgg.element(results.item(0))}else{defs=g.appendChild(this.create("defs"))}var elem;var className='__pv_gradient'+fill.id;results=undefined;if(!results){var instId='__pv_gradient'+fill.id+'_inst_'+(++gradient_definition_id);elem=defs.appendChild(this.create(isLinear?"linearGradient":"radialGradient"));elem.setAttribute("id",instId);elem.setAttribute("class",className);if(isLinear){var svgAngle=fill.angle-Math.PI/2;var diagAngle=Math.abs(svgAngle%(Math.PI/2))-Math.PI/4;var radius=Math.abs((Math.SQRT2/2)*Math.cos(diagAngle));var dirx=radius*Math.cos(svgAngle);var diry=radius*Math.sin(svgAngle);var x1=zeroRounding(0.5-dirx);var y1=zeroRounding(0.5-diry);var x2=zeroRounding(0.5+dirx);var y2=zeroRounding(0.5+diry);elem.setAttribute("x1",x1);elem.setAttribute("y1",y1);elem.setAttribute("x2",x2);elem.setAttribute("y2",y2)}else{}var stops=fill.stops;for(var i=0,S=stops.length;i1){t=tangents[1];p=points[pi];pi++;path+="C"+(p0.left+t0.x)+","+(p0.top+t0.y)+","+(p.left-t.x)+","+(p.top-t.y)+","+p.left+","+p.top;for(var i=2;i9){var tk=3/Math.sqrt(s);m[k]=tk*ak*d[k];m[k+1]=tk*bk*d[k]}}var len;for(var i=0;ifrom)&&!isInterpStepAfter){i--}if((j<=to)&&!isInterpStepBefore){j++}var fun=isInterpBasisCardinalOrMonotone&&(j-i>2)?this.areaPathCurve:this.areaPathStraight;d.push(fun.call(this,scenes,i,j-1,s));i=j-1}if(!d.length){return elm}var sop=stroke.opacity;elm=this.expect(elm,"path",scenes,from,{"shape-rendering":s.antialias?null:"crispEdges","pointer-events":addEvents?s.events:'none',"cursor":s.cursor,"d":"M"+d.join("ZM")+"Z","fill":fill.color,"fill-opacity":fill.opacity||null,"stroke":stroke.color,"stroke-opacity":sop||null,"stroke-width":sop?(s.lineWidth/this.scale):null,"stroke-linecap":s.lineCap,"stroke-linejoin":s.lineJoin,"stroke-miterlimit":s.strokeMiterLimit,"stroke-dasharray":sop?this.parseDasharray(s):null});if(s.svg)this.setAttributes(elm,s.svg);if(s.css)this.setStyle(elm,s.css);return this.append(elm,scenes,from)};pv.SvgScene.areaSegmentedSmart=function(elm,scenes){var eventsSegments=scenes.mark.$hasHandlers?[]:null;elm=this.eachLineAreaSegment(elm,scenes,function(elm,scenes,from,to){var segment=this.areaSegmentPaths(scenes,from,to);var pathsT=segment.top;var pathsB=segment.bottom;var fromp=from;if(eventsSegments){eventsSegments.push(segment)}var options={breakOnKeyChange:true,from:from,to:to};return this.eachLineAreaSegment(elm,scenes,options,function(elm,scenes,from,to){var s1=scenes[from];var fill=s1.fillStyle;var stroke=s1.strokeStyle;this.addFillStyleDefinition(scenes,fill);this.addFillStyleDefinition(scenes,stroke);if(from===to){return this.lineAreaDotAlone(elm,scenes,from)}var d=this.areaJoinPaths(pathsT,pathsB,from-fromp,to-fromp-1);var sop=stroke.opacity;var attrs={'shape-rendering':s1.antialias?null:'crispEdges','pointer-events':'none','cursor':s1.cursor,'d':d,'fill':fill.color,'fill-opacity':fill.opacity||null,'stroke':stroke.color,'stroke-opacity':sop||null,'stroke-width':sop?(s1.lineWidth/this.scale):null,'stroke-linecap':s1.lineCap,'stroke-linejoin':s1.lineJoin,'stroke-miterlimit':s1.strokeMiterLimit,'stroke-dasharray':sop?this.parseDasharray(s1):null};elm=this.expect(elm,'path',scenes,from,attrs,s1.css);return this.append(elm,scenes,from)})});if(eventsSegments){eventsSegments.forEach(function(segment){var from=segment.from;var pathsT=segment.top;var pathsB=segment.bottom;var P=pathsT.length;var attrsBase={'shape-rendering':'crispEdges','fill':'rgb(127,127,127)','fill-opacity':0.005,'stroke':null};pathsT.forEach(function(pathT,j){var i=from+j;var s=scenes[i];var events=s.events;if(events&&events!=="none"){var pathB=pathsB[P-j-1];var attrs=Object.create(attrsBase);attrs['pointer-events']=events;attrs.cursor=s.cursor;attrs.d=pathT.join("")+"L"+pathB[0].substr(1)+pathB[1]+"Z";elm=this.expect(elm,'path',scenes,i,attrs);elm=this.append(elm,scenes,i)}},this)},this)}return elm};pv.SvgScene.areaSegmentPaths=function(scenes,from,to){return this.areaSegmentCurvePaths(scenes,from,to)||this.areaSegmentStraightPaths(scenes,from,to)};pv.SvgScene.areaSegmentCurvePaths=function(scenes,from,to){var count=to-from+1;var s=scenes[from];var isBasis=s.interpolate==="basis";var isCardinal=!isBasis&&s.interpolate==="cardinal";if(isBasis||isCardinal||s.interpolate=="monotone"){var pointsT=[];var pointsB=[];for(var i=0;i2);if(curveInterpolated){switch(s.interpolate){case"basis":d+=this.curveBasis(scenes);break;case"cardinal":d+=this.curveCardinal(scenes,s.tension);break;case"monotone":d+=this.curveMonotone(scenes);break;default:curveInterpolated=false}}if(!curveInterpolated){for(var i=1;i1))break;return"A"+r+","+r+" 0 0,"+l+" "+s2.left+","+s2.top}case"step-before":return"V"+s2.top+"H"+s2.left;case"step-after":return"H"+s2.left+"V"+s2.top}return"L"+s2.left+","+s2.top};pv.SvgScene.lineSegmentPaths=function(scenes,from,to){var s=scenes[from];var paths;switch(s.interpolate){case"basis":paths=this.curveBasisSegments(scenes,from,to);break;case"cardinal":paths=this.curveCardinalSegments(scenes,s.tension,from,to);break;case"monotone":paths=this.curveMonotoneSegments(scenes,from,to);break}if(!paths||!paths.length){paths=[];for(var i=from+1;i<=to;i++){var s1=scenes[i-1];var s2=scenes[i];paths.push(["M"+s1.left+","+s1.top,this.lineSegmentPath(s1,s2)])}}return paths};pv.strokeMiterLimit=4;pv.SvgScene.pathJoin=function(s0,s1,s2,s3){var pts=[];var miterLimit,miterRatio,miterLength;var w1=s1.lineWidth/this.scale;var p1=pv.vector(s1.left,s1.top);var p2=pv.vector(s2.left,s2.top);var p21=p2.minus(p1);var v21=p21.perp().norm();var w21=v21.times(w1/2);var a=p1.plus(w21);var d=p1.minus(w21);var b=p2.plus(w21);var c=p2.minus(w21);if(!s0||!s0.visible){pts.push(d,a)}else{var p0=pv.vector(s0.left,s0.top);var p10=p1.minus(p0);var v10=p10.perp().norm();var v1=v10.plus(v21).norm();var am=this.lineIntersect(p1,v1,a,p21);var dm=this.lineIntersect(p1,v1,d,p21);miterLength=am.minus(dm).length();var w0=s0.lineWidth/this.scale;var w10avg=(w1+w0)/2;miterRatio=miterLength/w10avg;miterLimit=s1.strokeMiterLimit||pv.strokeMiterLimit;if(miterRatio<=miterLimit){pts.push(dm,am)}else{var p12=p21.times(-1);var v1Outer=p10.norm().plus(p12.norm()).norm();var bevel10=p1.plus(v1Outer.times(w10avg/2));if(v1Outer.dot(v21)>=0){pts.push(dm,bevel10,a)}else{pts.push(d,bevel10,am)}}}if(!s3||!s3.visible){pts.push(b,c)}else{var p3=pv.vector(s3.left,s3.top);var p32=p3.minus(p2);var v32=p32.perp().norm();var v2=v32.plus(v21).norm();var bm=this.lineIntersect(p2,v2,b,p21);var cm=this.lineIntersect(p2,v2,c,p21);miterLength=bm.minus(cm).length();var w3=s3.lineWidth/this.scale;var w31avg=(w3+w1)/2;miterRatio=miterLength/w31avg;miterLimit=s2.strokeMiterLimit||pv.strokeMiterLimit;if(miterRatio<=miterLimit){pts.push(bm,cm)}else{var p23=p32.times(-1);var v2Outer=p21.norm().plus(p23.norm()).norm();var bevel31=p2.plus(v2Outer.times(w31avg/2));if(v2Outer.dot(v21)>=0){pts.push(b,bevel31,cm)}else{pts.push(bm,bevel31,c)}}}var pt=pts.shift();return"M"+pt.x+","+pt.y+"L"+pts.map(function(pt2){return pt2.x+","+pt2.y}).join(" ")};pv.SvgScene.lineIntersect=function(o1,d1,o2,d2){return o1.plus(d1.times(o2.minus(o1).dot(d2.perp())/d1.dot(d2.perp())))};pv.SvgScene.lineJoinPaths=function(paths,from,to){var d=paths[from].join("");for(var i=from+1;i<=to;i++){d+=paths[i][1]}return d};pv.SvgScene.lineAreaDotAlone=function(elm,scenes,i){return elm};pv.SvgScene.eachLineAreaSegment=function(elm,scenes,keyArgs,lineAreaSegment){if(typeof keyArgs==='function'){lineAreaSegment=keyArgs;keyArgs=null}var breakOnKeyChange=pv.get(keyArgs,'breakOnKeyChange',false);var from=pv.get(keyArgs,'from')||0;var to=pv.get(keyArgs,'to',scenes.length-1);var ki,kf;if(breakOnKeyChange){ki=[];kf=[]}var i=from;while(i<=to){var si=scenes[i];if(!this.isSceneVisible(si)){i++;continue}if(breakOnKeyChange){this.lineAreaSceneKey(si,ki)}var i2;var f=i;while(true){var f2=f+1;if(f2>to){i2=f2;break}var sf=scenes[f2];if(!this.isSceneVisible(sf)){i2=f2+1;break}f=f2;if(breakOnKeyChange){this.lineAreaSceneKey(sf,kf);if(!this.equalSceneKeys(ki,kf)){i2=f;break}}}elm=lineAreaSegment.call(this,elm,scenes,i,f,keyArgs);i=i2}return elm};pv.SvgScene.lineAreaSceneKey=function(s,k){k[0]=s.fillStyle.key;k[1]=s.strokeStyle.key;k[2]=s.lineWidth;k[3]=(s.strokeDasharray||'none');k[4]=s.interpolate;return k};pv.SvgScene.isSceneVisible=function(s){return s.visible&&(s.fillStyle.opacity>0||s.strokeStyle.opacity>0)};pv.SvgScene.equalSceneKeys=function(ka,kb){for(var i=0,K=ka.length;i=2*Math.PI){if(r1){p="M0,"+r2+"A"+r2+","+r2+" 0 1,1 0,"+(-r2)+"A"+r2+","+r2+" 0 1,1 0,"+r2+"M0,"+r1+"A"+r1+","+r1+" 0 1,1 0,"+(-r1)+"A"+r1+","+r1+" 0 1,1 0,"+r1+"Z"}else{p="M0,"+r2+"A"+r2+","+r2+" 0 1,1 0,"+(-r2)+"A"+r2+","+r2+" 0 1,1 0,"+r2+"Z"}}else{var sa=Math.min(s.startAngle,s.endAngle),ea=Math.max(s.startAngle,s.endAngle),c1=Math.cos(sa),c2=Math.cos(ea),s1=Math.sin(sa),s2=Math.sin(ea);if(r1){p="M"+r2*c1+","+r2*s1+"A"+r2+","+r2+" 0 "+((a=pv.propertyEvalNetIndex){pv.propertyEvalNetIndex=readNetIndex+1}}}return this.instance()[name]}};pv.Mark.funPropertyCaller=function(fun,cast){var stack=pv.Mark.stack;return function(){var value=fun.apply(this,stack);return value!=null?cast(value):value}};pv.Mark.prototype.setPropertyValue=function(name,v,def,cast,chain,tag){var type=!def<<1|(typeof v==="function");if(type&1&&cast){v=pv.Mark.funPropertyCaller(v,cast)}else if(v!=null&&cast){v=cast(v)}var propertiesMap=this.$propertiesMap;var properties=this.$properties;var p={name:name,id:pv.id(),value:v,type:type,tag:tag};var specified=propertiesMap[name];propertiesMap[name]=p;if(specified){for(var i=0;i1?v:null)};pv.Mark.prototype.zOrder=function(zOrder){if(!arguments.length){return this._zOrder}zOrder=(+zOrder)||0;if(this._zOrder!==zOrder){if(this._zOrder!==0&&this.parent){this.parent.zOrderChildCount--}this._zOrder=zOrder;if(this._zOrder!==0&&this.parent){this.parent.zOrderChildCount++}}return this};pv.Mark.prototype.anchor=function(name){if(!name)name="center";return new pv.Anchor(this).name(name).data(function(){return this.scene.target.map(function(s){return s.data})}).visible(function(){return this.scene.target[this.index].visible}).id(function(){return this.scene.target[this.index].id}).left(function(){var s=this.scene.target[this.index],w=s.width||0;switch(this.name()){case"bottom":case"top":case"center":return s.left+w/2;case"left":return null}return s.left+w}).top(function(){var s=this.scene.target[this.index],h=s.height||0;switch(this.name()){case"left":case"right":case"center":return s.top+h/2;case"top":return null}return s.top+h}).right(function(){var s=this.scene.target[this.index];return this.name()=="left"?s.right+(s.width||0):null}).bottom(function(){var s=this.scene.target[this.index];return this.name()=="top"?s.bottom+(s.height||0):null}).textAlign(function(){switch(this.name()){case"bottom":case"top":case"center":return"center";case"right":return"right"}return"left"}).textBaseline(function(){switch(this.name()){case"right":case"left":case"center":return"middle";case"top":return"top"}return"bottom"})};pv.Mark.prototype.anchorTarget=function(){return this.target};pv.Mark.prototype.margin=function(n){return this.left(n).right(n).top(n).bottom(n)};pv.Mark.prototype.instance=function(defaultIndex){var scene=this.scene||this.parent.instance(-1).children[this.childIndex],index=!arguments.length||this.hasOwnProperty("index")?this.index:defaultIndex;return scene[index<0?scene.length-1:index]};pv.Mark.prototype.instances=function(source){var mark=this,index=[],scene;while(!(scene=mark.scene)){source=source.parent;index.push({index:source.index,childIndex:mark.childIndex});mark=mark.parent}while(index.length){var i=index.pop();scene=scene[i.index].children[i.childIndex]}if(this.hasOwnProperty("index")){var s=pv.extend(scene[this.index]);s.right=s.top=s.left=s.bottom=0;return[s]}return scene};pv.Mark.prototype.first=function(){return this.scene[0]};pv.Mark.prototype.last=function(){return this.scene[this.scene.length-1]};pv.Mark.prototype.sibling=function(){return(this.index==0)?null:this.scene[this.index-1]};pv.Mark.prototype.cousin=function(){var p=this.parent,s=p&&p.sibling();return(s&&s.children)?s.children[this.childIndex][this.index]:null};pv.Mark.prototype.render=function(){if(this.parent&&!this.root.scene){this.root.render();return}this.renderCore()};pv.Mark.prototype.renderCore=function(){var parent=this.parent,stack=pv.Mark.stack;var indexes=[];for(var mark=this;mark.parent;mark=mark.parent){indexes.unshift(mark.childIndex)}function render(mark,depth,scale){mark.scale=scale;if(depth=0;i--){var p=properties[i];var pLeaf=seen[p.name];if(!pLeaf){seen[p.name]=p;switch(p.name){case"data":data=p;break;case"visible":case"id":required.push(p);break;default:types[p.type].push(p);break}}else if(pLeaf.type===3){var pRoot=pLeaf.root;if(!pRoot){pLeaf.proto=pLeaf.root=p}else if(!pRoot.proto){pRoot.proto=p;pLeaf.root=p}}}}while(mark=mark.proto)}bind(this);bind(this.defaults);types[1].reverse();types[3].reverse();var mark=this;do{for(var name in mark.properties){if(!(name in seen)){types[2].push(seen[name]={name:name,type:2,value:null})}}}while((mark=mark.proto));var defs=types[0].concat(types[1]);for(var i=0;i(net[p.name]||0)){net[p.name]=minNetIndex;var deps=p.dependents;if(deps){minNetIndex++;for(var depName in deps){if(deps.hasOwnProperty(depName)){var pDep=props[depName];if(pDep){propagateRecursive(pDep,minNetIndex)}}}}}}};pv.Mark.prototype.build=function(){var scene=this.scene,stack=pv.Mark.stack;if(!scene){scene=this.scene=[];scene.mark=this;scene.type=this.type;scene.childIndex=this.childIndex;if(this.parent){scene.parent=this.parent.scene;scene.parentIndex=this.parent.index}}if(this.target)scene.target=this.target.instances(scene);if(this.binds.defs.length){var defs=scene.defs;if(!defs)scene.defs=defs={};for(var i=0;id.id)){defs[p.name]={id:0,value:(p.type&1)?p.value.apply(this,stack):p.value}}}}var data=this.binds.data;data=data.type&1?data.value.apply(this,stack):data.value;var markProto=pv.Mark.prototype;stack.unshift(null);try{var L=scene.length=data.length;for(var i=0;inetIndex){var evalDeps=pv.propertyEvalDependencies;for(var depName in evalDeps){if(evalDeps.hasOwnProperty(depName)&&!evaluatedProps.hasOwnProperty(name)){if(!netDirtyProps){netDirtyProps={}}netDirtyProps[depName]=true}}this.updateNet(p,newNetIndex)}break;case 2:v=p.value;break;case 0:case 1:v=this.scene.defs[name].value;break}s[name]=v}}if(!netDirtyProps){break}prevNetDirtyProps=netDirtyProps;propertyIndexes=pv.numerate(properties,function(p){return p.name});properties.sort(function(pa,pb){var comp=pv.naturalOrder(net[pa.name]||0,net[pb.name]||0);if(!comp){comp=pv.naturalOrder(propertyIndexes[pa.name],propertyIndexes[pb.name])}return comp});propertyIndexes=null}}finally{pv.propertyEval=null;pv.propertyEvalNetIndex=null;pv.propertyEvalDependencies=null}};pv.Mark.prototype.buildInstance=function(s){this.buildProperties(s,this.binds.required);if(s.visible){if(this.index===0){this.buildPropertiesWithDepTracking(s,this.binds.optional)}else{this.buildProperties(s,this.binds.optional)}this.buildImplied(s)}};pv.Mark.prototype.buildImplied=function(s){var l=s.left;var r=s.right;var t=s.top;var b=s.bottom;var p=this.properties;var w=p.width?s.width:0;var h=p.height?s.height:0;var instance;var checked;if(w==null||r==null||l==null){instance=this.parent?this.parent.instance():null;checked=true;var width=instance?instance.width:(w+l+r);if(w==null){w=width-(r=r||0)-(l=l||0)}else if(r==null){if(l==null){l=r=(width-w)/2}else{r=width-w-l}}else{l=width-w-r}}if(h==null||b==null||t==null){if(!checked){instance=this.parent?this.parent.instance():null}var height=instance?instance.height:(h+t+b);if(h==null){h=height-(t=t||0)-(b=b||0)}else if(b==null){if(t==null){b=t=(height-h)/2}else{b=height-h-t}}else{t=height-h-b}}s.left=l;s.right=r;s.top=t;s.bottom=b;if(p.width)s.width=w;if(p.height)s.height=h;if(p.textStyle&&!s.textStyle)s.textStyle=pv.FillStyle.transparent;if(p.fillStyle&&!s.fillStyle)s.fillStyle=pv.FillStyle.transparent;if(p.strokeStyle&&!s.strokeStyle)s.strokeStyle=pv.FillStyle.transparent};pv.Mark.prototype.mouse=function(){var n=this.root.canvas(),ev=pv.event,x=ev.pageX,y=ev.pageY;var offset=pv.elementOffset(n);if(offset){x-=offset.left;y-=offset.top;var computed=pv.getWindow(n.ownerDocument).getComputedStyle(n,null);if(computed){x-=parseFloat(computed.paddingLeft||0);y-=parseFloat(computed.paddingTop||0)}}var t=pv.Transform.identity,p=this.properties.transform?this:this.parent,pz=[];do{pz.push(p)}while((p=p.parent));while((p=pz.pop())){var pinst=p.instance();t=t.translate(pinst.left,pinst.top).times(pinst.transform)}t=t.invert();return pv.vector(x*t.k+t.x,y*t.k+t.y)};pv.Mark.prototype.event=function(type,handler){handler=pv.functor(handler);var handlers=this.$handlers[type];if(!handlers){handlers=handler}else if(handlers instanceof Array){handlers.push(handler)}else{handlers=[handlers,handler]}this.$hasHandlers=true;this.$handlers[type]=handlers;return this};pv.Mark.prototype.context=function(scene,index,f){var proto=pv.Mark.prototype,stack=pv.Mark.stack,oscene=pv.Mark.scene,oindex=proto.index;function apply(scene,index){pv.Mark.scene=scene;proto.index=index;if(!scene){return}var that=scene.mark,mark=that,ancestors=[];do{ancestors.push(mark);stack.push(scene[index].data);mark.index=index;mark.scene=scene;index=scene.parentIndex;scene=scene.parent}while(mark=mark.parent);for(var i=ancestors.length-1,k=1;i>0;i--){mark=ancestors[i];mark.scale=k;k*=mark.scene[mark.index].transform.k}var children=that.children;if(children){var thatInstance=that.scene[that.index];for(var i=0,n=children.length;i0){var isLastLevel=level===L,childIndex;if(!isLastLevel){childIndex=indexes[level]}for(var index=0;index=3*Math.PI/2)};pv.Wedge.prototype.buildImplied=function(s){if(s.angle==null)s.angle=s.endAngle-s.startAngle;else if(s.endAngle==null)s.endAngle=s.startAngle+s.angle;pv.Mark.prototype.buildImplied.call(this,s)};pv.Wedge.prototype.getShapeCore=function(scenes,index){var s=scenes[index];return new pv.Shape.Wedge(s.left,s.top,s.innerRadius,s.outerRadius,s.startAngle,s.angle)};pv.Ease=(function(){function reverse(f){return function(t){return 1-f(1-t)}}function reflect(f){return function(t){return.5*(t<.5?f(2*t):(2-f(2-2*t)))}}function poly(e){return function(t){return t<0?0:t>1?1:Math.pow(t,e)}}function sin(t){return 1-Math.cos(t*Math.PI/2)}function exp(t){return t?Math.pow(2,10*(t-1))-0.001:0}function circle(t){return-(Math.sqrt(1-t*t)-1)}function elastic(a,p){var s;if(!p)p=0.45;if(!a||a<1){a=1;s=p/4}else s=p/(2*Math.PI)*Math.asin(1/a);return function(t){return t<=0||t>=1?t:-(a*Math.pow(2,10*(--t))*Math.sin((t-s)*(2*Math.PI)/p))}}function back(s){if(!s)s=1.70158;return function(t){return t*t*((s+1)*t-s)}}function bounce(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}var quad=poly(2),cubic=poly(3),elasticDefault=elastic(),backDefault=back();var eases={"linear":pv.identity,"quad-in":quad,"quad-out":reverse(quad),"quad-in-out":reflect(quad),"quad-out-in":reflect(reverse(quad)),"cubic-in":cubic,"cubic-out":reverse(cubic),"cubic-in-out":reflect(cubic),"cubic-out-in":reflect(reverse(cubic)),"sin-in":sin,"sin-out":reverse(sin),"sin-in-out":reflect(sin),"sin-out-in":reflect(reverse(sin)),"exp-in":exp,"exp-out":reverse(exp),"exp-in-out":reflect(exp),"exp-out-in":reflect(reverse(exp)),"circle-in":circle,"circle-out":reverse(circle),"circle-in-out":reflect(circle),"circle-out-in":reflect(reverse(circle)),"elastic-in":elasticDefault,"elastic-out":reverse(elasticDefault),"elastic-in-out":reflect(elasticDefault),"elastic-out-in":reflect(reverse(elasticDefault)),"back-in":backDefault,"back-out":reverse(backDefault),"back-in-out":reflect(backDefault),"back-out-in":reflect(reverse(backDefault)),"bounce-in":bounce,"bounce-out":reverse(bounce),"bounce-in-out":reflect(bounce),"bounce-out-in":reflect(reverse(bounce))};pv.ease=function(f){return eases[f]};return{reverse:reverse,reflect:reflect,linear:function(){return pv.identity},sin:function(){return sin},exp:function(){return exp},circle:function(){return circle},elastic:elastic,back:back,bounce:bounce,poly:poly}})();pv.Transition=function(mark){var that=this,ease=pv.ease("cubic-in-out"),duration=250,timer,onEndCallback;var interpolated={top:1,left:1,right:1,bottom:1,width:1,height:1,innerRadius:1,outerRadius:1,radius:1,startAngle:1,endAngle:1,angle:1,fillStyle:1,strokeStyle:1,lineWidth:1,eccentricity:1,tension:1,textAngle:1,textStyle:1,textMargin:1};var defaults=new pv.Transient();function ids(marks){var map={};for(var i=0;i.5){before[name]=after[name]}}}f.next=list.head;list.head=f}function interpolateInstance(list,before,after){for(var name in before){if(name=="children")continue;if(before[name]==after[name])continue;interpolateProperty(list,name,before,after)}if(before.children){for(var j=0;jx2)x2=p.x;if(p.y>y2)y2=p.y}var dx=x2-x1,dy=y2-y1;if(dx>dy)y2=y1+dx;else x2=x1+dy;this.xMin=x1;this.yMin=y1;this.xMax=x2;this.yMax=y2;function insert(n,p,x1,y1,x2,y2){if(isNaN(p.x)||isNaN(p.y))return;if(n.leaf){if(n.p){if((Math.abs(n.p.x-p.x)+Math.abs(n.p.y-p.y))<.01){insertChild(n,p,x1,y1,x2,y2)}else{var v=n.p;n.p=null;insertChild(n,v,x1,y1,x2,y2);insertChild(n,p,x1,y1,x2,y2)}}else{n.p=p}}else{insertChild(n,p,x1,y1,x2,y2)}}function insertChild(n,p,x1,y1,x2,y2){var sx=(x1+x2)*.5,sy=(y1+y2)*.5,right=p.x>=sx,bottom=p.y>=sy;n.leaf=false;switch((bottom<<1)+right){case 0:n=n.c1||(n.c1=new pv.Quadtree.Node());break;case 1:n=n.c2||(n.c2=new pv.Quadtree.Node());break;case 2:n=n.c3||(n.c3=new pv.Quadtree.Node());break;case 3:n=n.c4||(n.c4=new pv.Quadtree.Node());break}if(right)x1=sx;else x2=sx;if(bottom)y1=sy;else y2=sy;insert(n,p,x1,y1,x2,y2)}this.root=new pv.Quadtree.Node();for(p=particles;p;p=p.next)insert(this.root,p,x1,y1,x2,y2)};pv.Quadtree.Node=function(){this.leaf=true;this.c1=null;this.c2=null;this.c3=null;this.c4=null;this.p=null};pv.Force={};pv.Force.charge=function(k){var min=2,min1=1/min,max=500,max1=1/max,theta=.9,force={};if(!arguments.length)k=-40;force.constant=function(x){if(arguments.length){k=Number(x);return force}return k};force.domain=function(a,b){if(arguments.length){min=Number(a);min1=1/min;max=Number(b);max1=1/max;return force}return[min,max]};force.theta=function(x){if(arguments.length){theta=Number(x);return force}return theta};function accumulate(n){var cx=0,cy=0;n.cn=0;function accumulateChild(c){accumulate(c);n.cn+=c.cn;cx+=c.cn*c.cx;cy+=c.cn*c.cy}if(!n.leaf){if(n.c1)accumulateChild(n.c1);if(n.c2)accumulateChild(n.c2);if(n.c3)accumulateChild(n.c3);if(n.c4)accumulateChild(n.c4)}if(n.p){n.cn+=k;cx+=k*n.p.x;cy+=k*n.p.y}n.cx=cx/n.cn;n.cy=cy/n.cn}function forces(n,p,x1,y1,x2,y2){var dx=n.cx-p.x,dy=n.cy-p.y,dn=1/Math.sqrt(dx*dx+dy*dy);if((n.leaf&&(n.p!=p))||((x2-x1)*dnmin1)dn=min1;var kc=n.cn*dn*dn*dn,fx=dx*kc,fy=dy*kc;p.fx+=fx;p.fy+=fy}else if(!n.leaf){var sx=(x1+x2)*.5,sy=(y1+y2)*.5;if(n.c1)forces(n.c1,p,x1,y1,sx,sy);if(n.c2)forces(n.c2,p,sx,y1,x2,sy);if(n.c3)forces(n.c3,p,x1,sy,sx,y2);if(n.c4)forces(n.c4,p,sx,sy,x2,y2);if(dnmin1)dn=min1;if(n.p&&(n.p!=p)){var kc=k*dn*dn*dn,fx=dx*kc,fy=dy*kc;p.fx+=fx;p.fy+=fy}}}force.apply=function(particles,q){accumulate(q.root);for(var p=particles;p;p=p.next){forces(q.root,p,q.xMin,q.yMin,q.xMax,q.yMax)}};return force};pv.Force.drag=function(k){var force={};if(!arguments.length)k=.1;force.constant=function(x){if(arguments.length){k=x;return force}return k};force.apply=function(particles){if(k)for(var p=particles;p;p=p.next){p.fx-=k*p.vx;p.fy-=k*p.vy}};return force};pv.Force.spring=function(k){var d=.1,l=20,links,kl,force={};if(!arguments.length)k=.1;force.links=function(x){if(arguments.length){links=x;kl=x.map(function(l){return 1/Math.sqrt(Math.max(l.sourceNode.linkDegree,l.targetNode.linkDegree))});return force}return links};force.constant=function(x){if(arguments.length){k=Number(x);return force}return k};force.damping=function(x){if(arguments.length){d=Number(x);return force}return d};force.length=function(x){if(arguments.length){l=Number(x);return force}return l};force.apply=function(particles){for(var i=0;ipy1,bottom=sypx1,right=sxmax)max=r}for(var i=0;ix.max?x.max:p.x)}if(y)for(var p=particles;p;p=p.next){p.y=p.yy.max?y.max:p.y)}};return constraint};pv.Layout=function(){pv.Panel.call(this)};pv.Layout.prototype=pv.extend(pv.Panel);pv.Layout.prototype.property=pv.Mark.prototype.localProperty;pv.Layout.Network=function(){pv.Layout.call(this);var that=this;this.$id=pv.id();(this.node=new pv.Mark().data(function(){return that.nodes()}).strokeStyle("#1f77b4").fillStyle("#fff").left(function(n){return n.x}).top(function(n){return n.y})).parent=this;this.link=new pv.Mark().extend(this.node).data(function(p){return[p.sourceNode,p.targetNode]}).fillStyle(null).lineWidth(function(d,p){return p.linkValue*1.5}).strokeStyle("rgba(0,0,0,.2)");this.link.add=function(type){return that.add(pv.Panel).data(function(){return that.links()}).add(type).extend(this)};(this.label=new pv.Mark().extend(this.node).textMargin(7).textBaseline("middle").text(function(n){return n.nodeName||n.nodeValue}).textAngle(function(n){var a=n.midAngle;return pv.Wedge.upright(a)?a:(a+Math.PI)}).textAlign(function(n){return pv.Wedge.upright(n.midAngle)?"left":"right"})).parent=this};pv.Layout.Network.prototype=pv.extend(pv.Layout).property("nodes",function(v){return v.map(function(d,i){if(typeof d!="object")d={nodeValue:d};d.index=i;return d})}).property("links",function(v){return v.map(function(d){if(isNaN(d.linkValue))d.linkValue=isNaN(d.value)?1:d.value;return d})});pv.Layout.Network.prototype.reset=function(){this.$id=pv.id();return this};pv.Layout.Network.prototype.buildProperties=function(s,properties){if((s.$id||0)=this.$id)return true;s.$id=this.$id;s.nodes.forEach(function(d){d.linkDegree=0});s.links.forEach(function(d){var v=d.linkValue;(d.sourceNode||(d.sourceNode=s.nodes[d.source])).linkDegree+=v;(d.targetNode||(d.targetNode=s.nodes[d.target])).linkDegree+=v})};pv.Layout.Hierarchy=function(){pv.Layout.Network.call(this);this.link.strokeStyle("#ccc")};pv.Layout.Hierarchy.prototype=pv.extend(pv.Layout.Network);pv.Layout.Hierarchy.prototype.buildImplied=function(s){if(!s.links)s.links=pv.Layout.Hierarchy.links.call(this);pv.Layout.Network.prototype.buildImplied.call(this,s)};pv.Layout.Hierarchy.links=function(){return this.nodes().filter(function(n){return n.parentNode}).map(function(n){return{sourceNode:n,targetNode:n.parentNode,linkValue:1}})};pv.Layout.Hierarchy.NodeLink={buildImplied:function(s){var nodes=s.nodes,orient=s.orient,horizontal=/^(top|bottom)$/.test(orient),w=s.width,h=s.height;if(orient=="radial"){var ir=s.innerRadius,or=s.outerRadius;if(ir==null)ir=0;if(or==null)or=Math.min(w,h)/2}function radius(n){return n.parentNode?(n.depth*(or-ir)+ir):0}function midAngle(n){return(n.parentNode?(n.breadth-.25)*2*Math.PI:0)}function x(n){switch(orient){case"left":return n.depth*w;case"right":return w-n.depth*w;case"top":return n.breadth*w;case"bottom":return w-n.breadth*w;case"radial":return w/2+radius(n)*Math.cos(n.midAngle)}}function y(n){switch(orient){case"left":return n.breadth*h;case"right":return h-n.breadth*h;case"top":return n.depth*h;case"bottom":return h-n.depth*h;case"radial":return h/2+radius(n)*Math.sin(n.midAngle)}}for(var i=0;i0){var orient=s.orient,horizontal=/^(top|bottom)\/.test(orient),bh=this.parent[horizontal?"height":"width"](),bands=this._readData(data,values,s),B=bands.length;if(s.bandOrder==="reverse"){bands.reverse()}if(s.order==="reverse"){values.reverse();for(var b=0;b0&&horizRatio<=1)){horizRatio=1}if(w==null){w=band.w=wItems/horizRatio}else if(scene.horizontalMode==='expand'){var wItems2=horizRatio*w;if(wItems){var wScale=wItems2/wItems;for(var l=0;l1?((wItemsWithMargin-wItems)/(L-1)):0;for(var l=0;l0?band.vertiMargin:0;items=band.items;var resultPos=this._layoutItemsOfDir(+1,invertDir,items,vertiMargin,bx,yOffset),resultNeg;if(resultPos.existsOtherDir){resultNeg=this._layoutItemsOfDir(-1,invertDir,items,vertiMargin,bx,yOffset)}if(bDiffControl){if(Math.abs(bDiffControl)===1){var yOffset0=yOffset;yOffset=resultPos.yOffset;if(resultNeg){yOffset-=(yOffset0-resultNeg.yOffset)}}}else{yOffset=yZero}}};pv.Layout.Band.prototype._layoutItemsOfDir=function(stackDir,invertDir,items,vertiMargin,bx,yOffset){var existsOtherDir=false,vertiMargin2=vertiMargin/2,efDir=(invertDir?-stackDir:stackDir),reverseLayers=invertDir;for(var l=0,L=items.length;l0){item.y=yOffset+vertiMargin2;yOffset+=h}else{item.y=yOffset-(h-vertiMargin2);yOffset-=h}var h2=item.h-vertiMargin;item.h=h2>0?h2:0;item.x=bx-item.w/2}else{existsOtherDir=true}}return{existsOtherDir:existsOtherDir,yOffset:yOffset}};pv.Layout.Band.prototype._bindItemProps=function(bands,itemProps,orient,horizontal){var index=orient.indexOf("-"),ph=horizontal?"h":"w",pw=horizontal?"w":"h",px=index<0?(horizontal?"l":"b"):orient.charAt(index+1),py=orient.charAt(0);itemProps[px]=function(b,l){return bands[b].items[l].x};itemProps[py]=function(b,l){return bands[b].items[l].y};itemProps[pw]=function(b,l){return bands[b].items[l].w};itemProps[ph]=function(b,l){return bands[b].items[l].h||0}};pv.Layout.Treemap=function(){pv.Layout.Hierarchy.call(this);this.node.strokeStyle("#fff").fillStyle("rgba(31, 119, 180, .25)").width(function(n){return n.dx}).height(function(n){return n.dy});this.label.visible(function(n){return!n.firstChild}).left(function(n){return n.x+(n.dx/2)}).top(function(n){return n.y+(n.dy/2)}).textAlign("center").textAngle(function(n){return n.dx>n.dy?0:-Math.PI/2});(this.leaf=new pv.Mark().extend(this.node).fillStyle(null).strokeStyle(null).visible(function(n){return!n.firstChild})).parent=this;delete this.link};pv.Layout.Treemap.prototype=pv.extend(pv.Layout.Hierarchy).property("round",Boolean).property("paddingLeft",Number).property("paddingRight",Number).property("paddingTop",Number).property("paddingBottom",Number).property("mode",String).property("order",String);pv.Layout.Treemap.prototype.defaults=new pv.Layout.Treemap().extend(pv.Layout.Hierarchy.prototype.defaults).mode("squarify").order("ascending");pv.Layout.Treemap.prototype.padding=function(n){return this.paddingLeft(n).paddingRight(n).paddingTop(n).paddingBottom(n)};pv.Layout.Treemap.prototype.$size=function(d){return Number(d.nodeValue)};pv.Layout.Treemap.prototype.size=function(f){this.$size=pv.functor(f);return this};pv.Layout.Treemap.prototype.buildImplied=function(s){if(pv.Layout.Hierarchy.prototype.buildImplied.call(this,s))return;var that=this,nodes=s.nodes,root=nodes[0],stack=pv.Mark.stack,left=s.paddingLeft,right=s.paddingRight,top=s.paddingTop,bottom=s.paddingBottom,size=function(n){return n.size},round=s.round?Math.round:Number,mode=s.mode;function slice(row,sum,horizontal,x,y,w,h){for(var i=0,d=0;irmax)rmax=r;s+=r}s=s*s;l=l*l;return Math.max(l*rmax/s,s/(l*rmin))}function layout(n,i){var x=n.x+left,y=n.y+top,w=n.dx-left-right,h=n.dy-top-bottom;if(mode!="squarify"){slice(n.childNodes,n.size,mode=="slice"?true:mode=="dice"?false:i&1,x,y,w,h);return}var row=[],mink=Infinity,l=Math.min(w,h),k=w*h/n.size;if(n.size<=0)return;n.visitBefore(function(n){n.size*=k});function position(row){var horizontal=w==l,sum=pv.sum(row,size),r=l?round(sum/l):0;slice(row,sum,horizontal,x,y,horizontal?w:r,horizontal?r:h);if(horizontal){y+=r;h-=r}else{x+=r;w-=r}l=Math.min(w,h);return horizontal}var children=n.childNodes.slice();while(children.length){var child=children[children.length-1];if(!child.size){children.pop();continue}row.push(child);var k=ratio(row,l);if(k<=mink){children.pop();mink=k}else{row.pop();position(row);row.length=0;mink=Infinity}}if(position(row))for(var i=0;i0){moveSubtree(ancestor(vim,v,a),v,shift);sip+=shift;sop+=shift}sim+=vim.mod;sip+=vip.mod;som+=vom.mod;sop+=vop.mod;nr=nextRight(vim);nl=nextLeft(vip)}if(nr&&!nextRight(vop)){vop.thread=nr;vop.mod+=sim-sop}if(nl&&!nextLeft(vom)){vom.thread=nl;vom.mod+=sip-som;a=v}}return a}function nextLeft(v){return v.firstChild||v.thread}function nextRight(v){return v.lastChild||v.thread}function moveSubtree(wm,wp,shift){var subtrees=wp.number-wm.number;wp.change-=shift/subtrees;wp.shift+=shift;wm.change+=shift/subtrees;wp.prelim+=shift;wp.mod+=shift}function executeShifts(v){var shift=0,change=0;for(var c=v.lastChild;c;c=c.previousSibling){c.prelim+=shift;c.mod+=shift;change+=c.change;shift+=c.shift+change}}function ancestor(vim,v,a){return(vim.ancestor.parentNode==v.parentNode)?vim.ancestor:a}function distance(depth,siblings){return(siblings?1:(group+1))/((orient=="radial")?depth:1)}var root=nodes[0];root.visitAfter(function(v,i){v.ancestor=v;v.prelim=0;v.mod=0;v.change=0;v.shift=0;v.number=v.previousSibling?(v.previousSibling.number+1):0;v.depth=i});firstWalk(root);secondWalk(root,-root.prelim,0);function midAngle(n){return(orient=="radial")?n.breadth/depth:0}function x(n){switch(orient){case"left":return n.depth;case"right":return w-n.depth;case"top":case"bottom":return n.breadth+w/2;case"radial":return w/2+n.depth*Math.cos(midAngle(n))}}function y(n){switch(orient){case"left":case"right":return n.breadth+h/2;case"top":return n.depth;case"bottom":return h-n.depth;case"radial":return h/2+n.depth*Math.sin(midAngle(n))}}root.visitAfter(function(v){v.breadth*=breadth;v.depth*=depth;v.midAngle=midAngle(v);v.x=x(v);v.y=y(v);if(v.firstChild)v.midAngle+=Math.PI;delete v.breadth;delete v.depth;delete v.ancestor;delete v.prelim;delete v.mod;delete v.change;delete v.shift;delete v.number;delete v.thread})};pv.Layout.Indent=function(){pv.Layout.Hierarchy.call(this);this.link.interpolate("step-after")};pv.Layout.Indent.prototype=pv.extend(pv.Layout.Hierarchy).property("depth",Number).property("breadth",Number);pv.Layout.Indent.prototype.defaults=new pv.Layout.Indent().extend(pv.Layout.Hierarchy.prototype.defaults).depth(15).breadth(15);pv.Layout.Indent.prototype.buildImplied=function(s){if(pv.Layout.Hierarchy.prototype.buildImplied.call(this,s))return;var nodes=s.nodes,bspace=s.breadth,dspace=s.depth,ax=0,ay=0;function position(n,breadth,depth){n.x=ax+depth++*dspace;n.y=ay+breadth++*bspace;n.midAngle=0;for(var c=n.firstChild;c;c=c.nextSibling){breadth=position(c,breadth,depth)}return breadth}position(nodes[0],1,1)};pv.Layout.Pack=function(){pv.Layout.Hierarchy.call(this);this.node.shapeRadius(function(n){return n.radius}).strokeStyle("rgb(31, 119, 180)").fillStyle("rgba(31, 119, 180, .25)");this.label.textAlign("center");delete this.link};pv.Layout.Pack.prototype=pv.extend(pv.Layout.Hierarchy).property("spacing",Number).property("order",String);pv.Layout.Pack.prototype.defaults=new pv.Layout.Pack().extend(pv.Layout.Hierarchy.prototype.defaults).spacing(1).order("ascending");pv.Layout.Pack.prototype.$radius=function(){return 1};pv.Layout.Pack.prototype.size=function(f){this.$radius=typeof f=="function"?function(){return Math.sqrt(f.apply(this,arguments))}:(f=Math.sqrt(f),function(){return f});return this};pv.Layout.Pack.prototype.buildImplied=function(s){if(pv.Layout.Hierarchy.prototype.buildImplied.call(this,s))return;var that=this,nodes=s.nodes,root=nodes[0];function radii(nodes){var stack=pv.Mark.stack;stack.unshift(null);for(var i=0,n=nodes.length;i.001}a=nodes[0];a.x=-a.radius;a.y=0;bound(a);if(nodes.length>1){b=nodes[1];b.x=b.radius;b.y=0;bound(b);if(nodes.length>2){c=nodes[2];place(a,b,c);bound(c);insert(a,c);a.p=c;insert(c,b);b=a.n;for(var i=3;i0){splice(a,j);b=j;i--}else if(isect<0){splice(j,b);a=j;i--}}}}var cx=(xMin+xMax)/2,cy=(yMin+yMax)/2,cr=0;for(var i=0;if.min){f.sim.step();render=true}}if(render)that.render()},42)}else for(var i=0;imaxDepth)maxDepth=depth;n.size=n.firstChild?pv.sum(n.childNodes,function(n){return n.size}):that.$size.apply(that,(stack[0]=n,stack))});stack.shift();switch(s.order){case"ascending":root.sort(function(a,b){return a.size-b.size});break;case"descending":root.sort(function(b,a){return a.size-b.size});break}root.minBreadth=0;root.breadth=.5;root.maxBreadth=1;root.visitBefore(function(n){var b=n.minBreadth,s=n.maxBreadth-b;for(var c=n.firstChild;c;c=c.nextSibling){c.minBreadth=b;b+=(c.size/n.size)*s;c.maxBreadth=b;c.breadth=(b+c.minBreadth)/2}});root.visitAfter(function(n,depth){n.minDepth=(depth-1)/maxDepth;n.maxDepth=(n.depth=depth/maxDepth)});pv.Layout.Hierarchy.NodeLink.buildImplied.call(this,s)};pv.Layout.Partition.Fill=function(){pv.Layout.Partition.call(this);pv.Layout.Hierarchy.Fill.constructor.call(this)};pv.Layout.Partition.Fill.prototype=pv.extend(pv.Layout.Partition);pv.Layout.Partition.Fill.prototype.buildImplied=function(s){if(pv.Layout.Partition.prototype.buildImplied.call(this,s))return;pv.Layout.Hierarchy.Fill.buildImplied.call(this,s)};pv.Layout.Arc=function(){pv.Layout.Network.call(this);var interpolate,directed,reverse,buildImplied=this.buildImplied;this.buildImplied=function(s){buildImplied.call(this,s);directed=s.directed;interpolate=s.orient=="radial"?"linear":"polar";reverse=s.orient=="right"||s.orient=="top"};this.link.data(function(p){var s=p.sourceNode,t=p.targetNode;return reverse!=(directed||(s.breadth>1)*size:null}).bottom(function(d,i){return mode=="mirror"?(i&1?null:(i+1>>1)*-size):((i&1||-1)*(i+1>>1)*size)}).fillStyle(function(d,i){return(i&1?red:blue)((i>>1)+1)});this.band.add=function(type){return that.add(pv.Panel).extend(bands).add(type).extend(this)}};pv.Layout.Horizon.prototype=pv.extend(pv.Layout).property("bands",Number).property("mode",String).property("backgroundStyle",pv.color).property("positiveStyle",pv.color).property("negativeStyle",pv.color);pv.Layout.Horizon.prototype.defaults=new pv.Layout.Horizon().extend(pv.Layout.prototype.defaults).bands(2).mode("offset").backgroundStyle("white").positiveStyle("#1f77b4").negativeStyle("#d62728");pv.Layout.Rollup=function(){pv.Layout.Network.call(this);var that=this,nodes,links,buildImplied=that.buildImplied;this.buildImplied=function(s){buildImplied.call(this,s);nodes=s.$rollup.nodes;links=s.$rollup.links};this.node.data(function(){return nodes}).shapeSize(function(d){return d.nodes.length*20});this.link.interpolate("polar").eccentricity(.8);this.link.add=function(type){return that.add(pv.Panel).data(function(){return links}).add(type).extend(this)}};pv.Layout.Rollup.prototype=pv.extend(pv.Layout.Network).property("directed",Boolean);pv.Layout.Rollup.prototype.x=function(f){this.$x=pv.functor(f);return this};pv.Layout.Rollup.prototype.y=function(f){this.$y=pv.functor(f);return this};pv.Layout.Rollup.prototype.buildImplied=function(s){if(pv.Layout.Network.prototype.buildImplied.call(this,s))return;var nodes=s.nodes,links=s.links,directed=s.directed,n=nodes.length,x=[],y=[],rnindex=0,rnodes={},rlinks={};function id(i){return x[i]+","+y[i]}var stack=pv.Mark.stack,o={parent:this};stack.unshift(null);for(var i=0;irtarget.index,linkId=reverse?rtarget.index+","+rsource.index:rsource.index+","+rtarget.index,rl=rlinks[linkId];if(!rl){rl=rlinks[linkId]={sourceNode:rsource,targetNode:rtarget,linkValue:0,links:[]}}rl.links.push(links[i]);rl.linkValue+=links[i].linkValue}s.$rollup={nodes:pv.values(rnodes),links:pv.values(rlinks)}};pv.Layout.Matrix=function(){pv.Layout.Network.call(this);var that=this,n,dx,dy,labels,pairs,buildImplied=that.buildImplied;this.buildImplied=function(s){buildImplied.call(this,s);n=s.nodes.length;dx=s.width/n;dy=s.height/n;labels=s.$matrix.labels;pairs=s.$matrix.pairs};this.link.data(function(){return pairs}).left(function(){return dx*(this.index%n)}).top(function(){return dy*Math.floor(this.index/n)}).width(function(){return dx}).height(function(){return dy}).lineWidth(1.5).strokeStyle("#fff").fillStyle(function(l){return l.linkValue?"#555":"#eee"}).parent=this;delete this.link.add;this.label.data(function(){return labels}).left(function(){return this.index&1?dx*((this.index>>1)+.5):0}).top(function(){return this.index&1?0:dy*((this.index>>1)+.5)}).textMargin(4).textAlign(function(){return this.index&1?"left":"right"}).textAngle(function(){return this.index&1?-Math.PI/2:0});delete this.node};pv.Layout.Matrix.prototype=pv.extend(pv.Layout.Network).property("directed",Boolean);pv.Layout.Matrix.prototype.sort=function(f){this.$sort=f;return this};pv.Layout.Matrix.prototype.buildImplied=function(s){if(pv.Layout.Network.prototype.buildImplied.call(this,s))return;var nodes=s.nodes,links=s.links,sort=this.$sort,n=nodes.length,index=pv.range(n),labels=[],pairs=[],map={};s.$matrix={labels:labels,pairs:pairs};if(sort)index.sort(function(a,b){return sort(nodes[a],nodes[b])});for(var i=0;i0.1;drag.canceled=!isDrag;cancelClick=isDrag&&(downElem===ev.target);if(!cancelClick){downElem=null}ev.stopPropagation();ev=wrapEvent(ev,drag);if(events){events.forEach(function(registration){pv.unlisten.apply(pv,registration)});events=null}var scene=drag.scene;var index=drag.index;try{scene.mark.context(scene,index,function(){shared.dragend.call(this,ev)})}finally{drag=null;delete scene[index].drag}}function wrapEvent(ev,drag){try{ev.drag=drag;return ev}catch(ex){}var ev2={};for(var p in ev){var v=ev[p];ev2[p]=typeof v!=='function'?v:bindEventFun(f,ev)}ev2._sourceEvent=ev;return ev2}function bindEventFun(f,ctx){return function(){return f.apply(ctx,arguments)}}function eventInterceptor(type,ev){if(cancelClick&&downElem===ev.target){cancelClick=false;downElem=null;return false}}mousedown.autoRender=function(_){if(arguments.length){shared.autoRender=!!_;return mousedown}return shared.autoRender};mousedown.positionConstraint=function(_){if(arguments.length){shared.positionConstraint=_;return mousedown}return shared.positionConstraint};return mousedown};pv.Behavior.drag=function(){var collapse=null;var kx=1;var ky=1;var v1;var shared={dragstart:function(ev){var drag=ev.drag;drag.type='drag';var p=drag.d;var fix=pv.vector(p.x,p.y);p.fix=fix;p.drag=drag;v1=fix.minus(drag.m1);var parent=this.parent;drag.max={x:parent.width()-(p.dx||0),y:parent.height()-(p.dy||0)};drag.min={x:0,y:0};if(shared.autoRender){this.render()}pv.Mark.dispatch("dragstart",drag.scene,drag.index,ev)},drag:function(ev){var drag=ev.drag;var m2=drag.m2;var p=drag.d;drag.m=v1.plus(m2);var constraint=shared.positionConstraint;if(constraint){constraint(drag)}var m=drag.m;if(kx){p.x=p.fix.x=shared.bound(m.x,'x')}if(ky){p.y=p.fix.y=shared.bound(m.y,'y')}if(shared.autoRender){this.render()}pv.Mark.dispatch("drag",drag.scene,drag.index,ev)},dragend:function(ev){var drag=ev.drag;var p=drag.d;p.fix=null;v1=null;if(shared.autoRender){this.render()}try{pv.Mark.dispatch('dragend',drag.scene,drag.index,ev)}finally{delete p.drag}}};var mousedown=pv.Behavior.dragBase(shared);mousedown.collapse=function(x){if(arguments.length){collapse=String(x);switch(collapse){case"y":kx=1;ky=0;break;case"x":kx=0;ky=1;break;default:kx=1;ky=1;break}return mousedown}return collapse};return mousedown};pv.Behavior.point=function(r){var unpoint,collapse=null,kx=1,ky=1,pointingPanel=null,r2=arguments.length?r*r:900;function search(scene,index){var s=scene[index],point={cost:Infinity};for(var i=(s.visible?s.children.length:0)-1;i>=0;i--){var child=s.children[i],mark=child.mark,p;if(mark.type=="panel"){mark.scene=child;for(var j=child.length-1;j>=0;j--){mark.index=j;p=search(child,j);if(p.cost=0;j--){var c=child[j],dx=v.x-c.left-(c.width||0)/2,dy=v.y-c.top-(c.height||0)/2,dd=kx*dx*dx+ky*dy*dy;if(ddr2))point=null;if(unpoint){if(point&&(unpoint.scene==point.scene)&&(unpoint.index==point.index))return;pv.Mark.dispatch("unpoint",unpoint.scene,unpoint.index,e)}if(unpoint=point){pv.Mark.dispatch("point",point.scene,point.index,e);if(!pointingPanel&&this.type==='panel'){pointingPanel=this;pointingPanel.event('mouseout',function(){var ev=arguments[arguments.length-1];mouseout.call(pointingPanel.scene.$g,ev)})}else{pv.listen(this.root.canvas(),"mouseout",mouseout)}}}function mouseout(e){if(unpoint&&!pv.ancestor(this,e.relatedTarget)){pv.Mark.dispatch("unpoint",unpoint.scene,unpoint.index,e);unpoint=null}}mousemove.collapse=function(x){if(arguments.length){collapse=String(x);switch(collapse){case"y":kx=1;ky=0;break;case"x":kx=0;ky=1;break;default:kx=1;ky=1;break}return mousemove}return collapse};return mousemove};pv.Behavior.select=function(){var collapse=null;var kx=1;var ky=1;var preserveLength=false;var shared={dragstart:function(ev){var drag=ev.drag;drag.type='select';var r=drag.d;r.drag=drag;drag.max={x:this.width(),y:this.height()};drag.min={x:0,y:0};var constraint=shared.positionConstraint;if(constraint){drag.m=drag.m.clone();constraint(drag)}var m=drag.m;if(kx){r.x=shared.bound(m.x,'x');if(!preserveLength){r.dx=0}}if(ky){r.y=shared.bound(m.y,'y');if(!preserveLength){r.dy=0}}pv.Mark.dispatch('selectstart',drag.scene,drag.index,ev)},drag:function(ev){var drag=ev.drag;var m1=drag.m1;var r=drag.d;drag.max.x=this.width();drag.max.y=this.height();var constraint=shared.positionConstraint;if(constraint){drag.m=drag.m.clone();constraint(drag)}var m=drag.m;if(kx){var bx=Math.min(m1.x,m.x);bx=shared.bound(bx,'x');r.x=bx;if(!preserveLength){var ex=Math.max(m.x,m1.x);ex=shared.bound(ex,'x');r.dx=ex-bx}}if(ky){var by=Math.min(m1.y,m.y);by=shared.bound(by,'y');r.y=by;if(!preserveLength){var ey=Math.max(m.y,m1.y);ey=shared.bound(ey,'y');r.dy=ey-by}}if(shared.autoRender){this.render()}pv.Mark.dispatch('select',drag.scene,drag.index,ev)},dragend:function(ev){var drag=ev.drag;try{pv.Mark.dispatch('selectend',drag.scene,drag.index,ev)}finally{var r=drag.d;delete r.drag}}};var mousedown=pv.Behavior.dragBase(shared);mousedown.collapse=function(x){if(arguments.length){collapse=String(x);switch(collapse){case"y":kx=1;ky=0;break;case"x":kx=0;ky=1;break;default:kx=1;ky=1;break}return mousedown}return collapse};mousedown.preserveLength=function(_){if(arguments.length){preserveLength=!!_;return mousedown}return preserveLength};return mousedown};pv.Behavior.resize=function(side){var preserveOrtho=false;var isLeftRight=(side==='left'||side==='right');var shared={dragstart:function(ev){var drag=ev.drag;drag.type='resize';var m1=drag.m1;var r=drag.d;r.drag=drag;switch(side){case"left":m1.x=r.x+r.dx;break;case"right":m1.x=r.x;break;case"top":m1.y=r.y+r.dy;break;case"bottom":m1.y=r.y;break}var parent=this.parent;drag.max={x:parent.width(),y:parent.height()};drag.min={x:0,y:0};pv.Mark.dispatch("resizestart",drag.scene,drag.index,ev)},drag:function(ev){var drag=ev.drag;var m1=drag.m1;var constraint=shared.positionConstraint;if(constraint){drag.m=drag.m.clone();constraint(drag)}var m=drag.m;var r=drag.d;if(!preserveOrtho||isLeftRight){var bx=Math.min(m1.x,m.x);var ex=Math.max(m.x,m1.x);bx=shared.bound(bx,'x');ex=shared.bound(ex,'x');r.x=bx;r.dx=ex-bx}if(!preserveOrtho||!isLeftRight){var by=Math.min(m1.y,m.y);var ey=Math.max(m.y,m1.y);bx=shared.bound(by,'y');ex=shared.bound(ey,'y');r.y=by;r.dy=ey-by}if(shared.autoRender){this.render()}pv.Mark.dispatch("resize",drag.scene,drag.index,ev)},dragend:function(ev){var drag=ev.drag;max=null;try{pv.Mark.dispatch('resizeend',drag.scene,drag.index,ev)}finally{var r=drag.d;delete r.drag}}};var mousedown=pv.Behavior.dragBase(shared);mousedown.preserveOrtho=function(_){if(arguments.length){preserveOrtho=!!_;return mousedown}return preserveOrtho};return mousedown};pv.Behavior.pan=function(){var scene,index,m1,v1,k,bound;function mousedown(){index=this.index;scene=this.scene;v1=pv.vector(pv.event.pageX,pv.event.pageY);m1=this.transform();k=1/(m1.k*this.scale);if(bound){bound={x:(1-m1.k)*this.width(),y:(1-m1.k)*this.height()}}}function mousemove(e){if(!scene)return;scene.mark.context(scene,index,function(){var x=(pv.event.pageX-v1.x)*k,y=(pv.event.pageY-v1.y)*k,m=m1.translate(x,y);if(bound){m.x=Math.max(bound.x,Math.min(0,m.x));m.y=Math.max(bound.y,Math.min(0,m.y))}this.transform(m).render()});pv.Mark.dispatch("pan",scene,index,e)}function mouseup(){scene=null}mousedown.bound=function(x){if(arguments.length){bound=Boolean(x);return this}return Boolean(bound)};pv.listen(window,"mousemove",mousemove);pv.listen(window,"mouseup",mouseup);return mousedown};pv.Behavior.zoom=function(speed){var bound;if(!arguments.length)speed=1/48;function mousewheel(e){var v=this.mouse(),k=pv.event.wheel*speed,m=this.transform().translate(v.x,v.y).scale((k<0)?(1e3/(1e3-k)):((1e3+k)/1e3)).translate(-v.x,-v.y);if(bound){m.k=Math.max(1,m.k);m.x=Math.max((1-m.k)*this.width(),Math.min(0,m.x));m.y=Math.max((1-m.k)*this.height(),Math.min(0,m.y))}this.transform(m).render();pv.Mark.dispatch("zoom",this.scene,this.index,e)}mousewheel.bound=function(x){if(arguments.length){bound=Boolean(x);return this}return Boolean(bound)};return mousewheel};pv.Geo=function(){};pv.Geo.projections={mercator:{project:function(latlng){return{x:latlng.lng/180,y:latlng.lat>85?1:latlng.lat<-85?-1:Math.log(Math.tan(Math.PI/4+pv.radians(latlng.lat)/2))/Math.PI}},invert:function(xy){return{lng:xy.x*180,lat:pv.degrees(2*Math.atan(Math.exp(xy.y*Math.PI))-Math.PI/2)}}},"gall-peters":{project:function(latlng){return{x:latlng.lng/180,y:Math.sin(pv.radians(latlng.lat))}},invert:function(xy){return{lng:xy.x*180,lat:pv.degrees(Math.asin(xy.y))}}},sinusoidal:{project:function(latlng){return{x:pv.radians(latlng.lng)*Math.cos(pv.radians(latlng.lat))/Math.PI,y:latlng.lat/90}},invert:function(xy){return{lng:pv.degrees((xy.x*Math.PI)/Math.cos(xy.y*Math.PI/2)),lat:xy.y*90}}},aitoff:{project:function(latlng){var l=pv.radians(latlng.lng),f=pv.radians(latlng.lat),a=Math.acos(Math.cos(f)*Math.cos(l/2));return{x:2*(a?(Math.cos(f)*Math.sin(l/2)*a/ Math.sin(a)) : 0) /Math.PI,y:2*(a?(Math.sin(f)*a/Math.sin(a)):0)/Math.PI}},invert:function(xy){var x=xy.x*Math.PI/2,y=xy.y*Math.PI/2;return{lng:pv.degrees(x/Math.cos(y)),lat:pv.degrees(y)}}},hammer:{project:function(latlng){var l=pv.radians(latlng.lng),f=pv.radians(latlng.lat),c=Math.sqrt(1+Math.cos(f)*Math.cos(l/2));return{x:2*Math.SQRT2*Math.cos(f)*Math.sin(l/2)/ c /3,y:Math.SQRT2*Math.sin(f)/c/1.5}},invert:function(xy){var x=xy.x*3,y=xy.y*1.5,z=Math.sqrt(1-x*x/16-y*y/4);return{lng:pv.degrees(2*Math.atan2(z*x,2*(2*z*z-1))),lat:pv.degrees(Math.asin(z*y))}}},identity:{project:function(latlng){return{x:latlng.lng/180,y:latlng.lat/90}},invert:function(xy){return{lng:xy.x*180,lat:xy.y*90}}}};pv.Geo.scale=function(p){var rmin={x:0,y:0},rmax={x:1,y:1},d=[],j=pv.Geo.projections.identity,x=pv.Scale.linear(-1,1).range(0,1),y=pv.Scale.linear(-1,1).range(1,0),c={lng:0,lat:0},lastLatLng,lastPoint;function scale(latlng){if(!lastLatLng||(latlng.lng!=lastLatLng.lng)||(latlng.lat!=lastLatLng.lat)){lastLatLng=latlng;var p=project(latlng);lastPoint={x:x(p.x),y:y(p.y)}}return lastPoint}function project(latlng){var offset={lng:latlng.lng-c.lng,lat:latlng.lat};return j.project(offset)}function invert(xy){var latlng=j.invert(xy);latlng.lng+=c.lng;return latlng}scale.x=function(latlng){return scale(latlng).x};scale.y=function(latlng){return scale(latlng).y};scale.ticks={lng:function(m){var lat,lng;if(d.length>1){var s=pv.Scale.linear();if(m==undefined)m=10;lat=s.domain(d,function(d){return d.lat}).ticks(m);lng=s.domain(d,function(d){return d.lng}).ticks(m)}else{lat=pv.range(-80,81,10);lng=pv.range(-180,181,10)}return lng.map(function(lng){return lat.map(function(lat){return{lat:lat,lng:lng}})})},lat:function(m){return pv.transpose(scale.ticks.lng(m))}};scale.invert=function(p){return invert({x:x.invert(p.x),y:y.invert(p.y)})};scale.domain=function(array,f){if(arguments.length){d=(array instanceof Array)?((arguments.length>1)?pv.map(array,f):array):Array.prototype.slice.call(arguments);if(d.length>1){var lngs=d.map(function(c){return c.lng});var lats=d.map(function(c){return c.lat});c={lng:(pv.max(lngs)+pv.min(lngs))/2,lat:(pv.max(lats)+pv.min(lats))/2};var n=d.map(project);x.domain(n,function(p){return p.x});y.domain(n,function(p){return p.y})}else{c={lng:0,lat:0};x.domain(-1,1);y.domain(-1,1)}lastLatLng=null;return this}return d};scale.range=function(min,max){if(arguments.length){if(typeof min=="object"){rmin={x:Number(min.x),y:Number(min.y)};rmax={x:Number(max.x),y:Number(max.y)}}else{rmin={x:0,y:0};rmax={x:Number(min),y:Number(max)}}x.range(rmin.x,rmax.x);y.range(rmax.y,rmin.y);lastLatLng=null;return this}return[rmin,rmax]};scale.projection=function(p){if(arguments.length){j=typeof p=="string"?pv.Geo.projections[p]||pv.Geo.projections.identity:p;return this.domain(d)}return p};pv.copyOwn(scale,pv.Scale.common);if(arguments.length)scale.projection(p);return scale}; \ No newline at end of file diff --git a/pacotes/ccc2/compacto/protovis-msie.js b/pacotes/ccc2/compacto/protovis-msie.js deleted file mode 100755 index d86f861..0000000 --- a/pacotes/ccc2/compacto/protovis-msie.js +++ /dev/null @@ -1 +0,0 @@ -pv.have_SVG=!!(document.createElementNS&&document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect);pv.have_VML=(function(d,a,b){a=d.createElement('div');a.innerHTML='';b=a.firstChild;b.style.behavior='url(#default#VML)';return b?typeof b.adj==='object':true})(document);if(!Array.prototype.indexOf){Array.prototype.indexOf=function(s,from){var n=this.length>>>0,i=(!isFinite(from)||from<0)?0:(from>this.length)?this.length:from;for(;i',block:{'group':1,'shape':1,'shapetype':1,'line':1,'polyline':1,'curve':1,'rect':1,'roundrect':1,'oval':1,'arc':1,'image':1},caps:{'butt':'flat','round':'round','square':'square'},joins:{'bevel':'bevel','round':'round','miter':'miter'},cursorstyles:{'hand':'pointer','crosshair':1,'pointer':1,'move':1,'text':1,'wait':1,'help':1,'progress':1,'n-resize':1,'ne-resize':1,'nw-resize':1,'s-resize':1,'se-resize':1,'sw-resize':1,'e-resize':1,'w-resize':1},text_shim:null,text_dims:function(text,font){var shim=vml.text_shim||(vml.init(),vml.text_shim);shim.style.font=vml.processFont(font);shim.innerText=text;return{height:shim.offsetHeight,width:shim.offsetWidth}},_fontCache:{},_fontSubst:{'default':'Arial','sans-serif':'Arial','sansserif':'Arial','sans':'Arial','serif':'Times New Roman','dialog':'Arial','monospaced':'Courier New','dialoginput':'Courier New'},_fontWhiteListIE64Bit:{'agency fb':1,'aharoni':1,'algerian':1,'andalus':1,'angsana new':1,'angsanaupc':1,'aparajita':1,'arabic typesetting':1,'arial':1,'arial black':1,'arial narrow':1,'arial rounded mt bold':1,'arial unicode ms':1,'baskerville old face':1,'batang':1,'batangche':1,'bauhaus 93':1,'bell mt':1,'berlin sans fb':1,'berlin sans fb demi':1,'bernard mt condensed':1,'blackadder itc':1,'bodoni mt':1,'bodoni mt black':1,'bodoni mt condensed':1,'bodoni mt poster compressed':1,'book antiqua':1,'bookman old style':1,'bookshelf symbol 7':1,'bradley hand itc':1,'britannic bold':1,'broadway':1,'browallia new':1,'browalliaupc':1,'brush script mt':1,'calibri':1,'californian fb':1,'calisto mt':1,'cambria':1,'cambria math':1,'candara':1,'castellar':1,'centaur':1,'century':1,'century gothic':1,'century schoolbook':1,'chiller':1,'colonna mt':1,'comic sans ms':1,'consolas':1,'constantia':1,'cooper black':1,'copperplate gothic bold':1,'copperplate gothic light':1,'corbel':1,'cordia new':1,'cordiaupc':1,'courier new':1,'curlz mt':1,'daunpenh':1,'david':1,'dfkai-sb':1,'dilleniaupc':1,'dokchampa':1,'dotum':1,'dotumche':1,'ebrima':1,'edwardian script itc':1,'elephant':1,'engravers mt':1,'eras bold itc':1,'eras demi itc':1,'eras light itc':1,'eras medium itc':1,'estrangelo edessa':1,'eucrosiaupc':1,'euphemia':1,'fangsong':1,'felix titling':1,'footlight mt light':1,'forte':1,'franklin gothic book':1,'franklin gothic demi':1,'franklin gothic demi cond':1,'franklin gothic heavy':1,'franklin gothic medium':1,'franklin gothic medium cond':1,'frankruehl':1,'freesiaupc':1,'freestyle script':1,'french script mt':1,'gabriola':1,'garamond':1,'gautami':1,'georgia':1,'gigi':1,'gill sans mt':1,'gill sans mt condensed':1,'gill sans mt ext condensed bold':1,'gill sans ultra bold':1,'gill sans ultra bold condensed':1,'gisha':1,'gloucester mt extra condensed':1,'goudy old style':1,'goudy stout':1,'gulim':1,'gulimche':1,'gungsuh':1,'gungsuhche':1,'guttman adii':1,'guttman adii-light':1,'guttman aharoni':1,'guttman calligraphic':1,'guttman david':1,'guttman drogolin':1,'guttman frank':1,'guttman frnew':1,'guttman haim':1,'guttman haim-condensed':1,'guttman hatzvi':1,'guttman hodes':1,'guttman kav':1,'guttman kav-light':1,'guttman keren':1,'guttman logo1':1,'guttman mantova':1,'guttman mantova-decor':1,'guttman miryam':1,'guttman myamfix':1,'guttman rashi':1,'guttman stam':1,'guttman stam1':1,'guttman vilna':1,'guttman yad':1,'guttman yad-brush':1,'guttman yad-light':1,'guttman-aharoni':1,'guttman-aram':1,'guttman-courmir':1,'guttman-soncino':1,'guttman-toledo':1,'haettenschweiler':1,'harlow solid italic':1,'harrington':1,'high tower text':1,'impact':1,'imprint mt shadow':1,'informal roman':1,'irisupc':1,'iskoola pota':1,'jasmineupc':1,'jokerman':1,'juice itc':1,'kaiti':1,'kalinga':1,'kartika':1,'khmer ui':1,'kodchiangupc':1,'kokila':1,'kristen itc':1,'kunstler script':1,'lao ui':1,'latha':1,'leelawadee':1,'levenim mt':1,'lilyupc':1,'lucida bright':1,'lucida calligraphy':1,'lucida console':1,'lucida fax':1,'lucida handwriting':1,'lucida sans':1,'lucida sans typewriter':1,'lucida sans unicode':1,'magneto':1,'maiandra gd':1,'malgun gothic':1,'mangal':1,'marlett':1,'matura mt script capitals':1,'meiryo':1,'meiryo ui':1,'microsoft himalaya':1,'microsoft jhenghei':1,'microsoft new tai lue':1,'microsoft phagspa':1,'microsoft sans serif':1,'microsoft tai le':1,'microsoft uighur':1,'microsoft yahei':1,'microsoft yi baiti':1,'mingliu':1,'mingliu-extb':1,'mingliu_hkscs':1,'mingliu_hkscs-extb':1,'miriam':1,'miriam fixed':1,'mistral':1,'modern no. 20':1,'mongolian baiti':1,'monotype corsiva':1,'monotype hadassah':1,'moolboran':1,'ms gothic':1,'ms mincho':1,'ms outlook':1,'ms pgothic':1,'ms pmincho':1,'ms reference sans serif':1,'ms reference specialty':1,'ms ui gothic':1,'mt extra':1,'mv boli':1,'narkisim':1,'niagara engraved':1,'niagara solid':1,'nsimsun':1,'nyala':1,'ocr a extended':1,'old english text mt':1,'onyx':1,'palace script mt':1,'palatino linotype':1,'papyrus':1,'parchment':1,'perpetua':1,'perpetua titling mt':1,'plantagenet cherokee':1,'playbill':1,'pmingliu':1,'pmingliu-extb':1,'poor richard':1,'pristina':1,'raavi':1,'rage italic':1,'ravie':1,'rockwell':1,'rockwell condensed':1,'rockwell extra bold':1,'rod':1,'sakkal majalla':1,'script mt bold':1,'segoe print':1,'segoe script':1,'segoe ui':1,'segoe ui light':1,'segoe ui semibold':1,'segoe ui symbol':1,'shonar bangla':1,'showcard gothic':1,'shruti':1,'simhei':1,'simplified arabic':1,'simplified arabic fixed':1,'simsun':1,'simsun-extb':1,'snap itc':1,'stencil':1,'sylfaen':1,'symbol':1,'tahoma':1,'tempus sans itc':1,'times new roman':1,'toptype soncino':1,'traditional arabic':1,'trebuchet ms':1,'tunga':1,'tw cen mt':1,'tw cen mt condensed':1,'tw cen mt condensed extra bold':1,'utsaah':1,'vani':1,'verdana':1,'vijaya':1,'viner hand itc':1,'vivaldi':1,'vladimir script':1,'vrinda':1,'webdings':1,'wide latin':1,'wingdings':1,'wingdings 2':1,'wingdings 3':1},_defaultFontIE64Bit:'Arial',processFont:function(font){var processedFont=vml._fontCache[font];if(!processedFont){var shim=vml.text_shim||(vml.init(),vml.text_shim);var style=shim.style;style.font=font;var fontFamily=style.fontFamily;if(fontFamily.charAt(0)==='"'){fontFamily=fontFamily.substr(1,fontFamily.length-1)}var ffKey=fontFamily.toLowerCase();var substFF=vml._fontSubst[ffKey];if(substFF){fontFamily=substFF}else if(vml.is64Bit&&!vml._fontWhiteListIE64Bit[ffKey]){fontFamily=vml._defaultFontIE64Bit}style.fontFamily='"'+fontFamily+'"';vml._fontCache[font]=processedFont=style.font}return processedFont},d2r:Math.PI*2/360, get_dim:function(attr,target){var o=target||{};o.translate_x=0;o.translate_y=0;if(attr.transform){var t=/translate\((-?\d+(?:\.\d+)?(?:e-?\d+)?)(?:,(-?\d+(?:\.\d+)?(?:e-?\d+)?))?\)/.exec(attr.transform);if(t&&t[1]){o.translate_x=parseFloat(t[1])}if(t&&t[2]){o.translate_y=parseFloat(t[2])}var r=/rotate\((\d+\.\d+|\d+)\)/.exec(attr.transform);if(r){o.rotation=parseFloat(r[1])%360}}o.x=parseFloat(attr.x||0);o.y=parseFloat(attr.y||0);if('width'in attr){o.width=parseFloat(attr.width)}if('height'in attr){o.height=parseFloat(attr.height)}return o},solidFillStyle:{type:'solid'},elm_defaults:{"g":{rewrite:'span',attr:function(attr,style,elm,scenes,i){var d=vml.get_dim(attr);elm.style.cssText="position:absolute;zoom:1;left:"+(d.translate_x+d.x)+"px;top:"+(d.translate_y+d.y)+"px;"}},"line":{rewrite:'shape',attr:function(attr,style,elm,scenes,i){var x1=parseFloat(attr.x1||0),y1=parseFloat(attr.y1||0),x2=parseFloat(attr.x2||0),y2=parseFloat(attr.y2||0),r=vml.round;elm.coordorigin="0,0";elm.coordsize="21600,21600";vml.path(elm).v='M '+r(x1)+' '+r(y1)+' L '+r(x2)+' '+r(y2)+' E';vml.stroke(elm,attr,scenes,i)},css:"top:0px;left:0px;width:1000px;height:1000px"},"rect":{rewrite:'shape',attr:function(attr,style,elm,scenes,i){var d=vml.get_dim(attr),p=vml.path(elm),r=vml.round;elm.coordorigin="0,0";elm.coordsize="21600,21600";var x=r(d.translate_x+d.x),y=r(d.translate_y+d.y),w=r(d.width),h=r(d.height);p.v='M '+x+' '+y+' L '+(x+w)+' '+y+' L '+(x+w)+' '+(y+h)+' L '+x+' '+(y+h)+' x';vml.stroke(elm,attr,scenes,i);vml.fill(elm,attr,scenes,i)},css:"top:0px;left:0px;width:1000px;height:1000px"},"path":{rewrite:'shape',attr:function(attr,style,elm,scenes,i){var d=vml.get_dim(attr),es=elm.style;es.left=(d.translate_x+d.x)+"px";es.top=(d.translate_y+d.y)+"px";elm.coordorigin="0,0";elm.coordsize="21600,21600";elm._events=attr["pointer-events"]||'none';vml.path(elm,attr.d);vml.fill(elm,attr,scenes,i);vml.stroke(elm,attr,scenes,i)},css:"top:0px;left:0px;width:1000px;height:1000px"},"circle":{rewrite:'oval',attr:function(attr,style,elm,scenes,i){var d=vml.get_dim(attr),es=elm.style,cx=parseFloat(attr.cx||0)+0.7,cy=parseFloat(attr.cy||0)+0.7,r=parseFloat(attr.r||0)+0.5;es.top=(d.translate_y+cy-r)+"px";es.left=(d.translate_x+cx-r)+"px";es.width=(r*2)+"px";es.height=(r*2)+"px";vml.fill(elm,attr,scenes,i);vml.stroke(elm,attr,scenes,i)}},"text":{rewrite:'shape',attr:function(attr,style,elm,scenes,i){var d=vml.get_dim(attr);var es=elm.style;elm.stroked="False";elm.path="m0,0 l1,0 e";var tp=vml.textpath(elm);tp.string=attr.string;var tpStyle=tp.style;tpStyle['v-text-align']=attr.textAlign;tpStyle.font=attr.font;if(attr.textDecoration){tpStyle.textDecoration=attr.textDecoration}vml.path(elm).textpathok='True';var r=attr.rotation;if(r){r=180*r/Math.PI;r=-(~~r%360)*vml.d2r;if(r){var ct=Math.cos(r).toFixed(8),st=Math.sin(r).toFixed(8);var skew=vml.skew(elm);skew.on='true';skew.matrix=ct+","+st+","+ -st+","+ct+",0,0"}}var s=scenes[i];s.fillStyle=vml.solidFillStyle;vml.fill(elm,attr,scenes,i);s.fillStyle=null},css:"position:absolute;top:0px;left:0px;width:1px;height:1px;"},"svg":{rewrite:'span',css:'position:relative;overflow:hidden;display:inline-block;~display:block;'},"vml:path":{rewrite:'path'},"vml:stroke":{rewrite:'stroke'},"vml:fill":{rewrite:'fill'},"vml:textpath":{rewrite:'textpath'},"vml:skew":{rewrite:'skew'}},_elmcache:{'span':document.createElement('span'),'div':document.createElement('div')},createElement:function(type,reformat){var elm,cache=vml._elmcache,helper=vml.elm_defaults[type]||{};var tagName=helper.rewrite||type;if(tagName in cache){elm=cache[tagName].cloneNode(false)}else{cache[tagName]=document.createElement(vml.pre+tagName+vml.post);if(tagName in vml.block){cache[tagName].className+=' msvml_block'}elm=cache[tagName].cloneNode(false)}helper.css&&(elm.style.cssText=helper.css);return elm},_hex:pv.range(0,256).map(function(i){return pv.Format.pad("0",2,i.toString(16))}),_colorcache:{},color:function(value){var result=vml._colorcache[value];var rgb;if(!result&&(rgb=/^rgb\((\d+),(\d+),(\d+)\)$/i.exec(value))){vml._colorcache[value]=result='#'+vml._hex[rgb[1]]+vml._hex[rgb[2]]+vml._hex[rgb[3]]}return result||value},fill:function(elm,attr,scenes,i){var fill=elm.getElementsByTagName('fill')[0];if(!fill){fill=elm.appendChild(vml.createElement('vml:fill'))}var fillStyle=scenes[i].fillStyle;if(!attr.fill||!fillStyle||(fillStyle.type==='solid'&&attr.fill==='none')){fill.on='false'}else{fill.on='true';if(fillStyle.type==='solid'){fill.type='solid';fill.color=vml.color(attr.fill)}else{var isLinear=fillStyle.type==='lineargradient';fill.method='none';var stops=fillStyle.stops;var S=stops.length;if(S>0){var stopsText=[];for(var i=0;i1){p.v=vml.rewritePath(svgpath)}return p},skew:function(elm){var sk=elm.getElementsByTagName('skew')[0];if(!sk)sk=elm.appendChild(vml.createElement('vml:skew'));sk.on="false";return sk},textpath:function(elm){var tp=elm.getElementsByTagName('textpath')[0];if(!tp){tp=elm.appendChild(vml.createElement('vml:textpath'))}tp.style['v-text-align']='center';tp.style['v-text-kern']='true';tp.on="true";return tp},init:function(){if(!vml.text_shim){vml.text_shim=document.getElementById('pv_vml_text_shim')||document.createElement('span');vml.text_shim.id='protovisvml_text_shim';vml.text_shim.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline-block;white-space:nowrap;";document.body.appendChild(vml.text_shim)}if(!vml.styles){vml.styles=document.getElementById('protovisvml_styles')||document.createElement("style");vml.styles.id='protovisvml_styles';document.documentElement.firstChild.appendChild(vml.styles);vml.styles.styleSheet.addRule('.msvml','behavior:url(#default#VML);');vml.styles.styleSheet.addRule('.msvml_block','position:absolute;top:0;left:0;');try{if(!document.namespaces.pvml){document.namespaces.add('pvml','urn:schemas-microsoft-com:vml')}}catch(e){vml.pre='<';vml.post=' class="msvml" xmlns="urn:schemas-microsoft.com:vml">'}}},_pathcache:{},rewritePath:function(p,deb){var x=0,y=0,round=vml.round;if(!p){return p}if(p in vml._pathcache){return vml._pathcache[p]}p=p.replace(/(\d*)((\.*\d*)(e ?-?\d*))/g,"$1");var bits=p.match(/([MLHVCSQTAZ ][^MLHVCSQTAZ ]*)/gi);var np=[],lastcurve=[];var oldOp='';for(var i=0,bl=bits.length;i=2*Math.PI){if(r1){d="AE0,0 "+r2+","+r2+" 0 23592960"+"AL0,0 "+r1+","+r1+" 0 23592960"}else{d="AE0,0 "+r2+","+r2+" 0 23592960"}}else{var sa=Math.round(s.startAngle/Math.PI*11796480),a=Math.round(s.angle/Math.PI*11796480);if(r1){d="AE 0,0 "+r2+","+r2+" "+ -sa+" "+ -a+" 0,0 "+r1+","+r1+" "+ -(sa+a)+" "+a+"X"}else{d="M0,0"+"AE0,0 "+r2+","+r2+" "+ -sa+" "+ -a+"X"}}p.v=d;e=this.append(e,scenes,i)}return e}})()} \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvc.color.js b/pacotes/ccc2/compacto/pvc.color.js deleted file mode 100755 index 2f961d5..0000000 --- a/pacotes/ccc2/compacto/pvc.color.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){pvc.color={scale:colorScale,scales:colorScales};function colorScales(keyArgs){keyArgs||def.fail.argumentRequired('keyArgs');var type=keyArgs.type||def.fail.argumentRequired('keyArgs.type');switch(type){case'linear':return new pvc.color.LinearScalesBuild(keyArgs).buildMap();case'discrete':return new pvc.color.DiscreteScalesBuild(keyArgs).buildMap();case'normal':return new pvc.color.NormalScalesBuild(keyArgs).buildMap()}throw def.error.argumentInvalid('scaleType',"Unexistent scale type '{0}'.",[type])}function colorScale(keyArgs){keyArgs||def.fail.argumentRequired('keyArgs');var type=keyArgs.type||def.fail.argumentRequired('keyArgs.type');switch(type){case'linear':return new pvc.color.LinearScalesBuild(keyArgs).build();case'discrete':return new pvc.color.DiscreteScalesBuild(keyArgs).build();case'normal':return new pvc.color.NormalScalesBuild(keyArgs).build()}throw def.error.argumentInvalid('scaleType',"Unexistent scale type '{0}'.",[type])}def.type('pvc.color.ScalesBuild').init(function(keyArgs){this.keyArgs=keyArgs;this.data=keyArgs.data||def.fail.argumentRequired('keyArgs.data');this.domainDimName=keyArgs.colorDimension||def.fail.argumentRequired('keyArgs.colorDimension');this.domainDim=this.data.dimensions(this.domainDimName);var dimType=this.domainDim.type;if(!dimType.isComparable){this.domainComparer=null;pvc.log("Color value dimension should be comparable. Generated color scale may be invalid.")}else{this.domainComparer=function(a,b){return dimType.compare(a,b)}}this.nullRangeValue=keyArgs.colorNull?pv.color(keyArgs.colorNull):pv.Color.transparent;this.domainRangeCountDif=0}).add({build:function(){this.range=this._getRange();this.desiredDomainCount=this.range.length+this.domainRangeCountDif;var domain=this._getDomain();return this._createScale(domain)},buildMap:function(){this.range=this._getRange();this.desiredDomainCount=this.range.length+this.domainRangeCountDif;var createCategoryScale;if(this.keyArgs.normPerBaseCategory){createCategoryScale=function(leafData){var domain=this._ensureDomain(null,false,leafData);return this._createScale(domain)}}else{var domain=this._getDomain(),scale=this._createScale(domain);createCategoryScale=def.fun.constant(scale)}return this._createCategoryScalesMap(createCategoryScale)},_createScale:def.method({isAbstract:true}),_createCategoryScalesMap:function(createCategoryScale){return this.data.children().object({name:function(leafData){return leafData.absKey},value:createCategoryScale,context:this})},_getRange:function(){var keyArgs=this.keyArgs,range=keyArgs.colors||['red','yellow','green'];if(keyArgs.colorMin!=null&&keyArgs.colorMax!=null){range=[keyArgs.colorMin,keyArgs.colorMax]}else if(keyArgs.colorMin!=null){range.unshift(keyArgs.colorMin)}else if(keyArgs.colorMax!=null){range.push(keyArgs.colorMax)}return range.map(function(c){return pv.color(c)})},_getDataExtent:function(data){var extent=data.dimensions(this.domainDimName).extent({visible:true});if(!extent){return null}var min=extent.min.value,max=extent.max.value;if(max==min){if(max>=1){min=max-1}else{max=min+1}}return{min:min,max:max}},_getDomain:function(){var domain=this.keyArgs.colorDomain;if(domain!=null){if(this.domainComparer){domain.sort(this.domainComparer)}if(domain.length>this.desiredDomainCount){domain=domain.slice(0,this.desiredDomainCount)}}else{domain=[]}return this._ensureDomain(domain,true,this.data)},_ensureDomain:function(domain,doDomainPadding,data){var extent;if(domain&&doDomainPadding){var domainPointsMissing=this.desiredDomainCount-domain.length;if(domainPointsMissing>0){extent=this._getDataExtent(data);if(extent){switch(domainPointsMissing){case 1:if(this.domainComparer){def.array.insert(domain,extent.max,this.domainComparer)}else{domain.push(extent.max)}break;case 2:if(this.domainComparer){def.array.insert(domain,extent.min,this.domainComparer);def.array.insert(domain,extent.max,this.domainComparer)}else{domain.unshift(extent.min);domain.push(extent.max)}break;default:if(pvc.debug>=2){pvc.log("Ignoring option 'colorDomain' due to unsupported length."+def.format(" Should have '{0}', but instead has '{1}'.",[this.desiredDomainCount,domain.length]))}domain=null}}}}if(!domain){extent||(extent=this._getDataExtent(data));if(extent){var min=extent.min,max=extent.max;var step=(max-min)/(this.desiredDomainCount-1);domain=pv.range(min,max+step,step)}}return domain}});def.type('pvc.color.LinearScalesBuild',pvc.color.ScalesBuild).add({_createScale:function(domain){var scale=pv.Scale.linear();if(domain){scale.domain.apply(scale,domain)}scale.range.apply(scale,this.range);return scale}});def.type('pvc.color.DiscreteScalesBuild',pvc.color.ScalesBuild).init(function(keyArgs){this.base(keyArgs);this.domainRangeCountDif=1}).add({_createScale:function(domain){var Dl=domain.length-1,range=this.range,nullRangeValue=this.nullRangeValue,Rl=range.length-1;function scale(val){if(val==null){return nullRangeValue}for(var i=0;i1){pvc.debug=1}['log','info','trace','warn','group','groupEnd'].forEach(function(p){pvc[p]=def.noop});pvc.error=function(e){if(e&&typeof e==='object'&&e.message){e=e.message}throw new Error("[pvChart ERROR]: "+e)}}}installPvcLog();pvc.logError=pvc.error;pv.error=pvc.error;function syncTipsyLog(){var tip=pv.Behavior.tipsy;if(tip&&tip.setDebug){tip.setDebug(pvc.debug);tip.log=pvc.log}}syncTipsyLog();pvc.defaultCompatVersion=function(compatVersion){var defaults=pvc.BaseChart.prototype.defaults;if(compatVersion!=null){return defaults.compatVersion=compatVersion}return defaults.compatVersion};pvc.cloneMatrix=function(m){return m.map(function(d){return d.slice()})};pvc.stringify=function(t,keyArgs){var maxLevel=def.get(keyArgs,'maxLevel')||5;var out=[];pvc.stringifyRecursive(out,t,maxLevel,keyArgs);return out.join('')};pvc.stringifyRecursive=function(out,t,remLevels,keyArgs){if(remLevels>0){remLevels--;switch(typeof t){case'undefined':return out.push('undefined');case'object':if(!t){out.push('null');return true}if(def.fun.is(t.stringify)){return t.stringify(out,remLevels,keyArgs)}if(t instanceof Array){out.push('[');t.forEach(function(item,index){if(index){out.push(', ')}if(!pvc.stringifyRecursive(out,item,remLevels,keyArgs)){out.pop()}});out.push(']')}else{var ownOnly=def.get(keyArgs,'ownOnly',true);if(t===def.global){out.push('');return true}if(def.fun.is(t.cloneNode)){out.push('');return true}if(remLevels>1&&t.constructor!==Object){remLevels=1;ownOnly=true}out.push('{');var first=true;for(var p in t){if(!ownOnly||def.hasOwnProp.call(t,p)){if(!first){out.push(', ')}out.push(p+': ');if(!pvc.stringifyRecursive(out,t[p],remLevels,keyArgs)){out.pop();if(!first){out.pop()}}else if(first){first=false}}}if(first){var s=''+t;if(s!=='[object Object]'){out.push('{'+s+'}')}}out.push('}')}return true;case'number':out.push(''+(Math.round(100000*t)/100000)); return true;case'boolean':out.push(''+t);return true;case'string':out.push(JSON.stringify(t));return true;case'function':if(def.get(keyArgs,'funs',false)){out.push(JSON.stringify(t.toString().substr(0,13)+'...'));return true}return false}out.push("'new ???'");return true}};pvc.orientation={vertical:'vertical',horizontal:'horizontal'};pvc.extensionTag='extension';pvc.extendType=function(type,exts,names){if(exts){var exts2;var addExtension=function(ext,name){if(ext!==undefined){if(!exts2){exts2={}}exts2[name]=def.fun.to(ext)}};if(names){names.forEach(function(name){addExtension(exts[name],name)})}else{def.each(addExtension)}if(exts2){type.add(exts2)}}};pv.Mark.prototype.hasDelegateValue=function(name,tag){var p=this.$propertiesMap[name];if(p){return(!tag||p.tag===tag)}if(this.proto){return this.proto.hasDelegateValue(name,tag)}return false};pvc.defaultColorScheme=null;pvc.brighterColorTransform=function(color){return(color.rgb?color:pv.color(color)).brighter(0.6)};pvc.setDefaultColorScheme=function(colors){return pvc.defaultColorScheme=pvc.colorScheme(colors)};pvc.defaultColor=pv.Colors.category10()('?');pvc.colorScheme=function(colors){if(colors==null){return null}if(typeof colors==='function'){if(!colors.hasOwnProperty('range')){return colors}colors=colors.range()}else{colors=def.array.as(colors)}if(!colors.length){return null}return function(){var scale=pv.colors(colors);scale.domain.apply(scale,arguments);return scale}},pvc.createColorScheme=function(colors){return pvc.colorScheme(colors)||pvc.defaultColorScheme||pv.Colors.category10};pvc.toGrayScale=function(color,alpha,maxGrayLevel,minGrayLevel){color=pv.color(color);var avg=0.299*color.r+0.587*color.g+0.114*color.b;if(maxGrayLevel===undefined){maxGrayLevel=200}else if(maxGrayLevel==null){maxGrayLevel=255}if(minGrayLevel===undefined){minGrayLevel=30}else if(minGrayLevel==null){minGrayLevel=0}var delta=(maxGrayLevel-minGrayLevel);if(delta<=0){avg=maxGrayLevel}else{avg=minGrayLevel+(avg/255)*delta}if(alpha==null){alpha=color.opacity}else if(alpha<0){alpha=(-alpha)*color.opacity}avg=Math.round(avg);return pv.rgb(avg,avg,avg,alpha)};pvc.removeTipsyLegends=function(){try{$('.tipsy').remove()}catch(e){}};pvc.createDateComparer=function(parser,key){if(!key){key=pv.identity}return function(a,b){return parser.parse(key(a))-parser.parse(key(b))}};pvc.time={intervals:{'y':31536e6,'m':2592e6,'d30':2592e6,'w':6048e5,'d7':6048e5,'d':864e5,'h':36e5,'M':6e4,'s':1e3,'ms':1},withoutTime:function(t){return new Date(t.getFullYear(),t.getMonth(),t.getDate())},weekday:{previousOrSelf:function(t,toWd){var wd=t.getDay();var difDays=wd-toWd;if(difDays){var previousOffset=difDays<0?(7+difDays):difDays;t=new Date(t-previousOffset*pvc.time.intervals.d)}return t},nextOrSelf:function(t,toWd){var wd=t.getDay();var difDays=wd-toWd;if(difDays){var nextOffset=difDays>0?(7-difDays):-difDays;t=new Date(t+nextOffset*pvc.time.intervals.d)}return t},closestOrSelf:function(t,toWd){var wd=t.getDay();var difDays=wd-toWd;if(difDays){var D=pvc.time.intervals.d;var sign=difDays>0?1:-1;difDays=Math.abs(difDays);if(difDays>=4){t=new Date(t.getTime()+sign*(7-difDays)*D)}else{t=new Date(t.getTime()-sign*difDays*D)}}return t}}};pv.Format.createParser=function(pvFormat){function parse(value){return pvFormat.parse(value)}return parse};pv.Format.createFormatter=function(pvFormat){function format(value){return value!=null?pvFormat.format(value):""}return format};pvc.buildTitleFromName=function(name){return def.firstUpperCase(name).replace(/([a-z\d])([A-Z])/,"$1 $2")};pvc.buildIndexedId=function(prefix,index){if(index>0){return prefix+""+(index+1)}return prefix};pvc.splitIndexedId=function(indexedId){var match=/^(.*?)(\d*)$/.exec(indexedId);var index=null;if(match[2]){index=Number(match[2]);if(index<=1){index=1}else{index--}}return[match[1],index]};function unwrapExtensionOne(id,prefix){if(id){if(def.object.is(id)){return id.abs}return prefix?(prefix+def.firstUpperCase(id)):id}return prefix}var oneNullArray=[null];pvc.makeExtensionAbsId=function(id,prefix){if(!id){return prefix}return def.query(prefix||oneNullArray).selectMany(function(oneprefix){return def.query(id).select(function(oneid){return unwrapExtensionOne(oneid,oneprefix)})}).where(def.truthy).array()};pvc.parseDistinctIndexArray=function(value,max){value=def.array.as(value);if(value==null){return null}if(max==null){max=Infinity}var a=def.query(value).select(function(index){return+index}).where(function(index){return!isNaN(index)&&index>=0&&index<=max}).distinct().array();return a.length?a:null};pvc.parseLegendClickMode=function(clickMode){if(!clickMode){clickMode='none'}switch(clickMode){case'toggleSelected':case'toggleVisible':case'none':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'legendClickMode' option value: '"+clickMode+"'. Assuming 'none'.")}clickMode='none';break}return clickMode};pvc.parseShape=function(shape){if(shape){switch(shape){case'square':case'circle':case'diamond':case'triangle':case'cross':case'bar':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'shape' option value: '"+shape+"'.")}shape=null;break}}return shape};pvc.parseContinuousColorScaleType=function(scaleType){if(scaleType){switch(scaleType){case'linear':case'normal':case'discrete':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'ScaleType' option value: '"+scaleType+"'.")}scaleType=null;break}}return scaleType};pvc.parseDomainScope=function(scope,orientation){if(scope){switch(scope){case'cell':case'global':break;case'section':if(!orientation){throw def.error.argumentRequired('orientation')}scope=orientation==='y'?'row':'column';break;case'column':case'row':if(orientation&&orientation!==(scope==='row'?'y':'x')){scope='section';if(pvc.debug>=2){pvc.log("[Warning] Invalid 'DomainScope' option value: '"+scope+"' for the orientation: '"+orientation+"'.")}}break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'DomainScope' option value: '"+scope+"'.")}scope=null;break}}return scope};pvc.parseDomainRoundingMode=function(mode){if(mode){switch(mode){case'none':case'nice':case'tick':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'DomainRoundMode' value: '"+mode+"'.")}mode=null;break}}return mode};pvc.parseOverlappedLabelsMode=function(mode){if(mode){switch(mode){case'leave':case'hide':break;default:if(pvc.debug>=2){pvc.log("[Warning] Invalid 'OverlappedLabelsMode' option value: '"+mode+"'.")}mode=null;break}}return mode};pvc.castNumber=function(value){if(value!=null){value=+value;if(isNaN(value)){value=null}}return value};pvc.parseWaterDirection=function(value){if(value){switch(value){case'up':case'down':return value}if(pvc.debug>=2){pvc.log("[Warning] Invalid 'WaterDirection' value: '"+value+"'.")}}};pvc.parseTrendType=function(value){if(value){if(value==='none'){return value}if(pvc.trends.has(value)){return value}if(pvc.debug>=2){pvc.log("[Warning] Invalid 'TrendType' value: '"+value+"'.")}}};pvc.parseNullInterpolationMode=function(value){if(value){switch(value){case'none':case'linear':case'zero':return value}if(pvc.debug>=2){pvc.log("[Warning] Invalid 'NullInterpolationMode' value: '"+value+"'.")}}};pvc.parseAlign=function(side,align){var align2,isInvalid;if(side==='left'||side==='right'){align2=align&&pvc.BasePanel.verticalAlign[align];if(!align2){align2='middle';isInvalid=!!align}}else{align2=align&&pvc.BasePanel.horizontalAlign[align];if(!align2){align2='center';isInvalid=!!align}}if(isInvalid&&pvc.debug>=2){pvc.log(def.format("Invalid alignment value '{0}'. Assuming '{1}'.",[align,align2]))}return align2};pvc.parseAnchor=function(anchor){if(anchor){switch(anchor){case'top':case'left':case'center':case'bottom':case'right':return anchor}if(pvc.debug>=2){pvc.log(def.format("Invalid anchor value '{0}'.",[anchor]))}}};pvc.parseAnchorWedge=function(anchor){if(anchor){switch(anchor){case'outer':case'inner':case'center':case'start':case'end':return anchor}if(pvc.debug>=2){pvc.log(def.format("Invalid wedge anchor value '{0}'.",[anchor]))}}};pvc.unionExtents=function(result,range){if(!result){if(!range){return null}result={min:range.min,max:range.max}}else if(range){if(range.minresult.max){result.max=range.max}}return result};pvc.Sides=function(sides){if(sides!=null){this.setSides(sides)}};pvc.Sides.hnames='left right'.split(' ');pvc.Sides.vnames='top bottom'.split(' ');pvc.Sides.names='left right top bottom'.split(' ');pvc.Sides.namesSet=pv.dict(pvc.Sides.names,def.retTrue);pvc.parsePosition=function(side,defaultSide){if(side&&!def.hasOwn(pvc.Sides.namesSet,side)){if(!defaultSide){defaultSide='left'}if(pvc.debug>=2){pvc.log(def.format("Invalid position value '{0}. Assuming '{1}'.",[side,defaultSide]))}side=defaultSide}return side};pvc.Sides.as=function(v){if(v!=null&&!(v instanceof pvc.Sides)){v=new pvc.Sides().setSides(v)}return v};pvc.Sides.prototype.stringify=function(out,remLevels,keyArgs){return pvc.stringifyRecursive(out,def.copyOwn(this),remLevels,keyArgs)};pvc.Sides.prototype.setSides=function(sides){if(typeof sides==='string'){var comps=sides.split(/\s+/).map(function(comp){return pvc.PercentValue.parse(comp)});switch(comps.length){case 1:this.set('all',comps[0]);return this;case 2:this.set('top',comps[0]);this.set('left',comps[1]);this.set('right',comps[1]);this.set('bottom',comps[0]);return this;case 3:this.set('top',comps[0]);this.set('left',comps[1]);this.set('right',comps[1]);this.set('bottom',comps[2]);return this;case 4:this.set('top',comps[0]);this.set('right',comps[1]);this.set('bottom',comps[2]);this.set('left',comps[3]);return this;case 0:return this}}else if(typeof sides==='number'){this.set('all',sides);return this}else if(typeof sides==='object'){if(sides instanceof pvc.PercentValue){this.set('all',sides)}else{this.set('all',sides.all);for(var p in sides){if(p!=='all'&&pvc.Sides.namesSet.hasOwnProperty(p)){this.set(p,sides[p])}}}return this}if(pvc.debug){pvc.log("Invalid 'sides' value: "+pvc.stringify(sides))}return this};pvc.Sides.prototype.set=function(prop,value){value=pvc.PercentValue.parse(value);if(value!=null){if(prop==='all'){pvc.Sides.names.forEach(function(p){this[p]=value},this)}else if(def.hasOwn(pvc.Sides.namesSet,prop)){this[prop]=value}}};pvc.Sides.prototype.resolve=function(width,height){if(typeof width==='object'){height=width.height;width=width.width}var sides={};pvc.Sides.names.forEach(function(side){var value=0;var sideValue=this[side];if(sideValue!=null){if(typeof(sideValue)==='number'){value=sideValue}else{value=sideValue.resolve((side==='left'||side==='right')?width:height)}}sides[side]=value},this);return pvc.Sides.updateSize(sides)};pvc.Sides.updateSize=function(sides){sides.width=(sides.left||0)+(sides.right||0);sides.height=(sides.bottom||0)+(sides.top||0);return sides};pvc.Sides.resolvedMax=function(a,b){var sides={};pvc.Sides.names.forEach(function(side){sides[side]=Math.max(a[side]||0,b[side]||0)});return sides};pvc.Sides.inflate=function(sides,by){var sidesOut={};pvc.Sides.names.forEach(function(side){sidesOut[side]=(sides[side]||0)+by});return pvc.Sides.updateSize(sidesOut)};pvc.PercentValue=function(pct){this.percent=pct};pvc.PercentValue.prototype.resolve=function(total){return this.percent*total};pvc.PercentValue.parse=function(value){if(value!=null&&value!==''){switch(typeof value){case'number':return value;case'string':var match=value.match(/^(.+?)\s*(%)?$/);if(match){var n=+match[1];if(!isNaN(n)){if(match[2]){if(n>=0){return new pvc.PercentValue(n/100)}}else{return n}}}break;case'object':if(value instanceof pvc.PercentValue){return value}break}if(pvc.debug){pvc.log(def.format("Invalid margins component '{0}'",[''+value]))}}};pvc.PercentValue.resolve=function(value,total){return(value instanceof pvc.PercentValue)?value.resolve(total):value};var markRenderCore=pv.Mark.prototype.renderCore,markZOrder=pv.Mark.prototype.zOrder;pv.Mark.prototype.zOrder=function(zOrder){var borderPanel=this.borderPanel;if(borderPanel&&borderPanel!==this){return markZOrder.call(borderPanel,zOrder)}return markZOrder.call(this,zOrder)};pv.Mark.prototype.renderCore=function(){var root=this.root;root._renderId=(root._renderId||0)+1;if(pvc.debug>=25){pvc.log("BEGIN RENDER "+root._renderId)}markRenderCore.apply(this,arguments);if(pvc.debug>=25){pvc.log("END RENDER "+root._renderId)}};pv.Mark.prototype.renderId=function(){return this.root._renderId};pv.Mark.prototype.wrapper=function(wrapper){this._wrapper=wrapper;return this};pv.Mark.prototype.wrap=function(f,m){if(f&&def.fun.is(f)&&this._wrapper&&!f._cccWrapped){f=this._wrapper(f,m);f._cccWrapped=true}return f};pv.Mark.prototype.lock=function(prop,value){if(value!==undefined){this[prop](value)}(this._locked||(this._locked={}))[prop]=true;return this};pv.Mark.prototype.isIntercepted=function(prop){return this._intercepted&&this._intercepted[prop]};pv.Mark.prototype.isLocked=function(prop){return this._locked&&this._locked[prop]};pv.Mark.prototype.addMargin=function(name,margin){if(margin!==0){var staticValue=def.nullyTo(this.propertyValue(name),0),fMeasure=pv.functor(staticValue);this[name](function(){return margin+fMeasure.apply(this,arraySlice.call(arguments))})}return this};pv.Mark.prototype.addMargins=function(margins){var all=def.get(margins,'all',0);this.addMargin('left',def.get(margins,'left',all));this.addMargin('right',def.get(margins,'right',all));this.addMargin('top',def.get(margins,'top',all));this.addMargin('bottom',def.get(margins,'bottom',all));return this};pv.Mark.prototype.eachInstanceWithData=function(fun,ctx){this.eachInstance(function(scenes,index,t){if(scenes.mark.sign&&scenes[index].data){fun.call(ctx,scenes,index,t)}})};pv.Transform.prototype.transformHPosition=function(left){return this.x+(this.k*left)};pv.Transform.prototype.transformVPosition=function(top){return this.y+(this.k*top)};pv.Transform.prototype.transformLength=function(length){return this.k*length};var Size=def.type('pvc.Size').init(function(width,height){if(arguments.length===1){if(width!=null){this.setSize(width)}}else{if(width!=null){this.width=width}if(height!=null){this.height=height}}}).add({stringify:function(out,remLevels,keyArgs){return pvc.stringifyRecursive(out,def.copyOwn(this),remLevels,keyArgs)},setSize:function(size,keyArgs){if(typeof size==='string'){var comps=size.split(/\s+/).map(function(comp){return pvc.PercentValue.parse(comp)});switch(comps.length){case 1:this.set(def.get(keyArgs,'singleProp','all'),comps[0]);return this;case 2:this.set('width',comps[0]);this.set('height',comps[1]);return this;case 0:return this}}else if(typeof size==='number'){this.set(def.get(keyArgs,'singleProp','all'),size);return this}else if(typeof size==='object'){if(size instanceof pvc.PercentValue){this.set(def.get(keyArgs,'singleProp','all'),size)}else{this.set('all',size.all);for(var p in size){if(p!=='all'){this.set(p,size[p])}}}return this}if(pvc.debug){pvc.log("Invalid 'size' value: "+pvc.stringify(size))}return this},set:function(prop,value){if(value!=null&&(prop==='all'||def.hasOwn(pvc.Size.namesSet,prop))){value=pvc.PercentValue.parse(value);if(value!=null){if(prop==='all'){pvc.Size.names.forEach(function(p){this[p]=value},this)}else{this[prop]=value}}}return this},clone:function(){return new Size(this.width,this.height)},intersect:function(size){return new Size(Math.min(this.width,size.width),Math.min(this.height,size.height))},resolve:function(refSize){var size={};pvc.Size.names.forEach(function(length){var lengthValue=this[length];if(lengthValue!=null){if(typeof(lengthValue)==='number'){size[length]=lengthValue}else if(refSize){var refLength=refSize[length];if(refLength!=null){size[length]=lengthValue.resolve(refLength)}}}},this);return size}});pvc.Size.names=['width','height'];pvc.Size.namesSet=pv.dict(pvc.Size.names,def.retTrue);pvc.Size.toOrtho=function(value,anchor){if(value!=null){var a_ol;if(anchor){a_ol=pvc.BasePanel.orthogonalLength[anchor]}value=pvc.Size.to(value,{singleProp:a_ol});if(anchor){delete value[pvc.BasePanel.oppositeLength[a_ol]]}}return value};pvc.Size.to=function(v,keyArgs){if(v!=null&&!(v instanceof Size)){v=new Size().setSize(v,keyArgs)}return v};var Offset=def.type('pvc.Offset').init(function(x,y){if(arguments.length===1){if(x!=null){this.setOffset(x)}}else{if(x!=null){this.x=x}if(y!=null){this.y=y}}}).add({stringify:function(out,remLevels,keyArgs){return pvc.stringifyRecursive(out,def.copyOwn(this),remLevels,keyArgs)},setOffset:function(offset,keyArgs){if(typeof offset==='string'){var comps=offset.split(/\s+/).map(function(comp){return pvc.PercentValue.parse(comp)});switch(comps.length){case 1:this.set(def.get(keyArgs,'singleProp','all'),comps[0]);return this;case 2:this.set('x',comps[0]);this.set('y',comps[1]);return this;case 0:return this}}else if(typeof offset==='number'){this.set(def.get(keyArgs,'singleProp','all'),offset);return this}else if(typeof offset==='object'){this.set('all',offset.all);for(var p in offset){if(p!=='all'){this.set(p,offset[p])}}return this}if(pvc.debug){pvc.log("Invalid 'offset' value: "+pvc.stringify(offset))}return this},set:function(prop,value){if(value!=null&&def.hasOwn(pvc.Offset.namesSet,prop)){value=pvc.PercentValue.parse(value);if(value!=null){if(prop==='all'){pvc.Offset.names.forEach(function(p){this[p]=value},this)}else{this[prop]=value}}}},resolve:function(refSize){var offset={};pvc.Size.names.forEach(function(length){var offsetProp=pvc.Offset.namesSizeToOffset[length];var offsetValue=this[offsetProp];if(offsetValue!=null){if(typeof(offsetValue)==='number'){offset[offsetProp]=offsetValue}else if(refSize){var refLength=refSize[length];if(refLength!=null){offset[offsetProp]=offsetValue.resolve(refLength)}}}},this);return offset}});pvc.Offset.names=['x','y'];pvc.Offset.namesSet=pv.dict(pvc.Offset.names,def.retTrue);pvc.Offset.namesSizeToOffset={width:'x',height:'y'};pvc.Offset.namesSidesToOffset={left:'x',right:'x',top:'y',bottom:'y'};pvc.Offset.as=function(v){if(v!=null&&!(v instanceof Offset)){v=new Offset().setOffset(v)}return v}}());(function($){$.support.svg=$.support.svg||document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")}(jQuery)); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvc.options.js b/pacotes/ccc2/compacto/pvc.options.js deleted file mode 100755 index a329a78..0000000 --- a/pacotes/ccc2/compacto/pvc.options.js +++ /dev/null @@ -1 +0,0 @@ -def.scope(function(){function options(specs,context){specs||def.fail.argumentRequired('specs');var _infos={};def.each(specs,function(spec,name){var info=new OptionInfo(name,option,context,spec);_infos[info.name]=info});function resolve(name){var info=def.getOwn(_infos,name)||def.fail.operationInvalid("Undefined option '{0}'",[name]);return info.resolve()}function option(name,noDefault){var info=resolve(name);return noDefault&&!info.isSpecified?undefined:info.value}function isSpecified(name){return resolve(name).isSpecified}function specified(name){return option(name,true)}function isDefined(name){return def.hasOwn(_infos,name)}function specify(opts){return set(opts,false)}function defaults(opts){return set(opts,true)}function getDefaultValue(name){return resolve(name)._defaultValue}function set(opts,isDefault){for(var name in opts){var info=def.getOwn(_infos,name);if(info){var value=opts[name];if(value!==undefined){info.set(value,isDefault)}}}return option}option.option=option;option.specified=specified;option.isSpecified=isSpecified;option.isDefined=isDefined;option.defaultValue=getDefaultValue;option.specify=specify;option.defaults=defaults;return option}function resolvers(list){return function(optionInfo){for(var i=0,L=list.length;ilen*1.5){return pvc.text.trimToWidthBin(len,text,font,trimTerminator,before)}while(textLen>len){text=before?text.slice(1):text.slice(0,text.length-1);textLen=pv.Text.measure(text,font).width}return before?(trimTerminator+text):(text+trimTerminator)},trimToWidthBin:function(len,text,font,trimTerminator,before){var ilen=text.length,high=ilen-2,low=0,mid,textLen;while(low<=high&&high>0){mid=Math.ceil((low+high)/2);var textMid=before?text.slice(ilen-mid):text.slice(0,mid);textLen=pv.Text.measure(textMid,font).width;if(textLen>len){high=mid-1}else if(pv.Text.measure(before?text.slice(ilen-mid-1):text.slice(0,mid+1),font).widthlineWidth){if(line){lines.push(line)}line=word}else{line=nextLine}}}if(line){lines.push(line)}return lines},getLabelBBox:function(textWidth,textHeight,align,baseline,angle,margin){var polygon=pv.Label.getPolygon(textWidth,textHeight,align,baseline,angle,margin);var bbox=polygon.bbox();bbox.source=polygon;bbox.sourceAngle=angle;bbox.sourceAlign=align;bbox.sourceTextWidth=textWidth;return bbox}}; \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvc.trends.js b/pacotes/ccc2/compacto/pvc.trends.js deleted file mode 100755 index 4b4600a..0000000 --- a/pacotes/ccc2/compacto/pvc.trends.js +++ /dev/null @@ -1 +0,0 @@ -def.space('pvc.trends',function(trends){var _trends={};def.set(trends,'define',function(type,trendSpec){type||def.fail.argumentRequired('type');trendSpec||def.fail.argumentRequired('trendSpec');def.object.is(trendSpec)||def.fail.argumentInvalid('trendSpec',"Must be a trend specification object.");if(pvc.debug>=2&&def.hasOwn(_trends,type)){pvc.log(def.format("[WARNING] A trend type with the name '{0}' is already defined.",[type]))}var label=trendSpec.label||def.fail.argumentRequired('trendSpec.label');var model=trendSpec.model||def.fail.argumentRequired('trendSpec.model');def.fun.is(model)||def.fail.argumentInvalid('trendSpec.mode',"Must be a function.");var trendInfo={dataPartAtom:{v:'trend',f:label},type:type,label:label,model:model};_trends[type]=trendInfo},'get',function(type){type||def.fail.argumentRequired('type');return def.getOwn(_trends,type)||def.fail.operationInvalid("Undefined trend type '{0}'.",[type])},'has',function(type){return def.hasOwn(_trends,type)},'types',function(){return def.ownKeys(_trends)});trends.define('linear',{label:'Linear trend',model:function(options){var rows=def.get(options,'rows');var funX=def.get(options,'x');var funY=def.get(options,'y');var i=0;var N=0;var sumX=0;var sumY=0;var sumXY=0;var sumXX=0;var parseNum=function(value){return value!=null?(+value):NaN};while(rows.next()){var row=rows.item;var x=funX?parseNum(funX(row)):i;if(!isNaN(x)){var y=parseNum(funY(row));if(!isNaN(y)){N++;sumX+=x;sumY+=y;sumXY+=x*y;sumXX+=x*x}}i++}var alpha,beta;if(N>=2){var avgX=sumX/N;var avgY=sumY/N;var avgXY=sumXY/N;var avgXX=sumXX/N;var den=(avgXX-avgX*avgX);if(den===0){beta=0}else{beta=(avgXY-(avgX*avgY))/den}alpha=avgY-beta*avgX;return{alpha:alpha,beta:beta,reset:def.noop,sample:function(x){return alpha+beta*(+x)}}}}});trends.define('moving-average',{label:'Moving average',model:function(options){var W=Math.max(+(def.get(options,'periods')||3),2);var sum=0;var avgValues=[];return{reset:function(){sum=0;avgValues.length=0},sample:function(x,y,i){var L=W;if(y!=null){avgValues.unshift(y);sum+=y;L=avgValues.length;if(L>W){sum-=avgValues.pop();L=W}}return sum/L}}}});trends.define('weighted-moving-average',{label:'Weighted Moving average',model:function(options){var W=Math.max(+(def.get(options,'periods')||3),2);var sum=0;var numer=0;var avgValues=[];var L=0;var denom=0;return{reset:function(){sum=numer=denom=L=0;avgValues.length=0},sample:function(x,y){if(y!=null){if(L=2){this._log("[WARNING] Layout cannot change. Skipping calculation of overflow paddings.")}return}if(!this._layoutInfo.labelBBox){this._calcLabelBBox()}this._calcOverflowPaddingsFromLabelBBox()},_calcOverflowPaddingsFromLabelBBox:function(){var overflowPaddings=null;var layoutInfo=this._layoutInfo;var ticks=layoutInfo.ticks;var tickCount=ticks.length;if(tickCount){var paddings=layoutInfo.paddings;var labelBBox=layoutInfo.labelBBox;var isTopOrBottom=this.isAnchorTopOrBottom();var begSide=isTopOrBottom?'left':'top';var endSide=isTopOrBottom?'right':'bottom';var isDiscrete=this.scale.type==='discrete';var clientLength=layoutInfo.clientSize[this.anchorLength()];this.axis.setScaleRange(clientLength);var sideTickOffset;if(isDiscrete){var halfBand=this.scale.range().step/2; sideTickOffset=def.set({},begSide,halfBand,endSide,halfBand)}else{sideTickOffset=def.set({},begSide,this.scale(ticks[0]),endSide,clientLength-this.scale(ticks[tickCount-1]))}[begSide,endSide].forEach(function(side){var overflowPadding=this._getLabelBBoxQuadrantLength(labelBBox,side);if(overflowPadding>0){overflowPadding-=(paddings[side]||0);if(overflowPadding>0){overflowPadding-=sideTickOffset[side];if(overflowPadding>1){if(isDiscrete){overflowPadding*=1.05}if(!overflowPaddings){overflowPaddings={}}overflowPaddings[side]=overflowPadding}}}},this);if(pvc.debug>=6&&overflowPaddings){this._log("OverflowPaddings = "+pvc.stringify(overflowPaddings))}}layoutInfo.overflowPaddings=overflowPaddings},_calcMaxTextLengthThatFits:function(){var layoutInfo=this._layoutInfo;if(this.compatVersion()<=1){layoutInfo.maxTextWidth=null;return}var availableClientLength=layoutInfo.clientSize[this.anchorOrthoLength()];var efSize=Math.min(layoutInfo.axisSize,availableClientLength);if(efSize>=(layoutInfo.requiredAxisSize-this.tickLength)){layoutInfo.maxTextWidth=null}else{var labelBBox=layoutInfo.labelBBox;var maxOrthoLength=efSize-2*this.tickLength;var mostOrthoDistantPoint;var parallelDirection;switch(this.anchor){case'left':parallelDirection=pv.vector(0,1);mostOrthoDistantPoint=pv.vector(-maxOrthoLength,0);break;case'right':parallelDirection=pv.vector(0,1);mostOrthoDistantPoint=pv.vector(maxOrthoLength,0);break;case'top':parallelDirection=pv.vector(1,0);mostOrthoDistantPoint=pv.vector(0,-maxOrthoLength);break;case'bottom':parallelDirection=pv.vector(1,0);mostOrthoDistantPoint=pv.vector(0,maxOrthoLength);break}var orthoOutwardsDir=mostOrthoDistantPoint.norm();var corners=labelBBox.source.points();var botL=corners[0];var botR=corners[1];var topR=corners[2];var topL=corners[3];var topLRSideDir=topR.minus(topL);var botLRSideDir=botR.minus(botL);var intersect=pv.SvgScene.lineIntersect;var botI=intersect(mostOrthoDistantPoint,parallelDirection,botL,botLRSideDir);var topI=intersect(mostOrthoDistantPoint,parallelDirection,topL,topLRSideDir);var sideLRWidth=labelBBox.sourceTextWidth;var maxTextWidth=sideLRWidth;var botLI=botI.minus(botL);var botLILen=botLI.length();if(botLILen<=sideLRWidth&&botLI.dot(topLRSideDir)>=0){if(botL.dot(orthoOutwardsDir)=0){if(topL.dot(orthoOutwardsDir)=3){this._log("Trimming labels' text at length "+maxTextWidth.toFixed(2)+"px maxOrthoLength="+maxOrthoLength.toFixed(2)+"px")}}},_calcTicks:function(){var layoutInfo=this._layoutInfo;layoutInfo.textHeight=pv.Text.fontHeight(this.font);layoutInfo.maxTextWidth=null;this.axis.setTicks(null);switch(this.scale.type){case'discrete':this._calcDiscreteTicks();break;case'timeSeries':this._calcTimeSeriesTicks();break;case'numeric':this._calcNumberTicks(layoutInfo);break;default:throw def.error.operationInvalid("Undefined axis scale type")}this.axis.setTicks(layoutInfo.ticks);var clientLength=layoutInfo.clientSize[this.anchorLength()];this.axis.setScaleRange(clientLength);if(layoutInfo.maxTextWidth==null){layoutInfo.maxTextWidth=def.query(layoutInfo.ticksText).select(function(text){return pv.Text.measure(text,this.font).width},this).max()}layoutInfo._maxTextWidth=layoutInfo.maxTextWidth},_calcDiscreteTicks:function(){var layoutInfo=this._layoutInfo;var role=this.chart.visualRoles(this.roleName);var data=role.flatten(this.chart.data,{visible:true});layoutInfo.data=data;layoutInfo.ticks=data._children;var format,dimType;var grouping=role.grouping;if(grouping.isSingleDimension&&(dimType=grouping.firstDimensionType())&&(dimType.valueType===Date)){var extent=data.dimensions(dimType.name).extent();if(extent&&extent.min!==extent.max){var scale=new pv.Scale.linear(extent.min.value,extent.max.value);scale.ticks();var tickFormatter=this.axis.option('TickFormatter');if(tickFormatter){scale.tickFormatter(tickFormatter)}format=function(child){return scale.tickFormat(child.value)}}}if(!format){format=function(child){return child.absLabel}}layoutInfo.ticksText=data._children.map(format)},_calcTimeSeriesTicks:function(){this._calcContinuousTicks(this._layoutInfo)},_calcNumberTicks:function(){var desiredTickCount=this.desiredTickCount;if(desiredTickCount==null){if(this.isAnchorTopOrBottom()){this._calcNumberHTicks();return}desiredTickCount=this._calcNumberVDesiredTickCount()}this._calcContinuousTicks(this._layoutInfo,desiredTickCount)},_calcContinuousTicks:function(ticksInfo,desiredTickCount){this._calcContinuousTicksValue(ticksInfo,desiredTickCount);this._calcContinuousTicksText(ticksInfo)},_calcContinuousTicksValue:function(ticksInfo,desiredTickCount){ticksInfo.ticks=this.scale.ticks(desiredTickCount,{roundInside:this.domainRoundMode!=='tick',numberExponentMin:this.tickExponentMin,numberExponentMax:this.tickExponentMax});if(pvc.debug>4){this._log("DOMAIN: "+pvc.stringify(this.scale.domain()));this._log("TICKS: "+pvc.stringify(ticksInfo.ticks))}},_calcContinuousTicksText:function(ticksInfo){ticksInfo.ticksText=def.query(ticksInfo.ticks).select(function(tick){return this.scale.tickFormat(tick)},this).array()},_calcDiscreteTicksHidden:function(){return this._tickIncludeModulo=this._calcDiscreteTicksHiddenCore()},_calcDiscreteTicksHiddenCore:function(){var mode=this.axis.option('OverlappedLabelsMode');if(mode!=='hide'){return 1}var layoutInfo=this._layoutInfo;var ticks=layoutInfo.ticks;var tickCount=ticks.length;if(tickCount<=1){return 1}var b=this.scale.range().step;var h=layoutInfo.textHeight;var w=layoutInfo.maxTextWidth;if(!(w>0&&h>0&&b>0)){return 1}var sMin=h*this.labelSpacingMin;var a=layoutInfo.textAngle;var isTopOrBottom=this.isAnchorTopOrBottom();var sinOrCos=isTopOrBottom?'sin':'cos';var cosOrSin=!isTopOrBottom?'sin':'cos';var tickIncludeModulo=1;do{var bEf=tickIncludeModulo*b;var sBase=bEf*Math.abs(Math[sinOrCos](a))-h;var sOrtho=bEf*Math.abs(Math[cosOrSin](a))-w;if(sBase>=sMin||sOrtho>=sMin){break}tickIncludeModulo++}while(Math.ceil(tickCount/tickIncludeModulo)>1);if(tickIncludeModulo>1&&pvc.debug>=3){this._log("Showing only one in every "+tickIncludeModulo+" tick labels")}return tickIncludeModulo},_calcNumberVDesiredTickCount:function(){var layoutInfo=this._layoutInfo;var lineHeight=layoutInfo.textHeight*(1+Math.max(0,this.labelSpacingMin));var clientLength=layoutInfo.clientSize[this.anchorLength()];return Math.max(1,~~(clientLength/lineHeight))},_calcNumberHTicks:function(){var layoutInfo=this._layoutInfo;var clientLength=layoutInfo.clientSize[this.anchorLength()];var spacing=layoutInfo.textHeight*Math.max(0,this.labelSpacingMin);var desiredTickCount=this._calcNumberHDesiredTickCount(spacing);var doLog=(pvc.debug>=7);var dir,prevResultTickCount;var ticksInfo,lastBelow,lastAbove;do{if(doLog){this._log("calculateNumberHTicks TickCount IN desired = "+desiredTickCount)}ticksInfo={};this._calcContinuousTicksValue(ticksInfo,desiredTickCount);var ticks=ticksInfo.ticks;var resultTickCount=ticks.length;if(ticks.exponentOverflow){if(dir==null){if(ticks.exponent===this.exponentMin){lastBelow=ticksInfo;dir=1}else{lastAbove=ticksInfo;dir=-1}}else if(dir===1){if(lastBelow){ticksInfo=lastBelow}break}else{if(lastAbove){ticksInfo=lastAbove}break}}else if(prevResultTickCount==null||resultTickCount!==prevResultTickCount){if(doLog){this._log("calculateNumberHTicks TickCount desired/resulting = "+desiredTickCount+" -> "+resultTickCount)}prevResultTickCount=resultTickCount;this._calcContinuousTicksText(ticksInfo);var length=this._calcNumberHLength(ticksInfo,spacing);var excessLength=ticksInfo.excessLength=length-clientLength;var pctError=ticksInfo.error=Math.abs(excessLength/clientLength);if(doLog){this._log("calculateNumberHTicks error="+(excessLength>=0?"+":"-")+(ticksInfo.error*100).toFixed(0)+"% count="+resultTickCount+" step="+ticks.step);this._log("calculateNumberHTicks Length client/resulting = "+clientLength+" / "+length+" spacing = "+spacing)}if(excessLength>0){if(desiredTickCount===1){if(resultTickCount===3&&pctError<=1){ticksInfo.ticks.splice(1,1);ticksInfo.ticksText.splice(1,1);ticksInfo.ticks.step*=2}else{ticksInfo.ticks.length=1;ticksInfo.ticksText.length=1}delete ticksInfo.maxTextWidth;break}if(lastBelow){ticksInfo=lastBelow;break}lastAbove=ticksInfo;dir=-1}else{if(pctError<=0.05||dir===-1){break}lastBelow=ticksInfo;dir=+1}}desiredTickCount+=dir}while(true);if(ticksInfo){layoutInfo.ticks=ticksInfo.ticks;layoutInfo.ticksText=ticksInfo.ticksText;layoutInfo.maxTextWidth=ticksInfo.maxTextWidth;if(pvc.debug>=5){this._log("calculateNumberHTicks RESULT error="+(ticksInfo.excessLength>=0?"+":"-")+(ticksInfo.error*100).toFixed(0)+"% count="+ticksInfo.ticks.length+" step="+ticksInfo.ticks.step)}}if(doLog){this._log("calculateNumberHTicks END")}},_calcNumberHDesiredTickCount:function(spacing){var layoutInfo=this._layoutInfo;var domainTextLength=this.scale.domain().map(function(tick){tick=+tick.toFixed(2);var text=this.scale.tickFormat(tick);return pv.Text.measure(text,this.font).width},this);var avgTextLength=Math.max((domainTextLength[1]+domainTextLength[0])/2,layoutInfo.textHeight);var clientLength=layoutInfo.clientSize[this.anchorLength()];return Math.max(1,~~(clientLength/(avgTextLength+spacing)))},_calcNumberHLength:function(ticksInfo,spacing){var ticksText=ticksInfo.ticksText;var maxTextWidth=def.query(ticksText).select(function(text){return pv.Text.measure(text,this.font).width},this).max();return Math.max(maxTextWidth,(ticksText.length-1)*(maxTextWidth+spacing))},_createCore:function(){if(this.scale.isNull){return}var clientSize=this._layoutInfo.clientSize;var paddings=this._layoutInfo.paddings;var begin_a=this.anchorOrtho();var end_a=this.anchorOpposite(begin_a);var size_a=this.anchorOrthoLength(begin_a);var rMin=this.ruleCrossesMargin?-paddings[begin_a]:0;var rMax=clientSize[size_a]+(this.ruleCrossesMargin?paddings[end_a]:0);var rSize=rMax-rMin;var ruleParentPanel=this.pvPanel;this._rSize=rSize;var rootScene=this._getRootScene();this.pvRule=new pvc.visual.Rule(this,this.pvPanel,{extensionId:'rule'}).lock('data',[rootScene]).override('defaultColor',def.fun.constant("#666666")).lock(this.anchorOpposite(),0).lock(begin_a,rMin).lock(size_a,rSize).pvMark.zOrder(30).strokeDasharray(null).lineCap('square');if(this.isDiscrete){if(this.useCompositeAxis){this.renderCompositeOrdinalAxis()}else{this.renderOrdinalAxis()}}else{this.renderLinearAxis()}},_getExtensionId:function(){return''},_getRootScene:function(){if(!this._rootScene){var rootScene=this._rootScene=new pvc.visual.CartesianAxisRootScene(null,{panel:this,group:this._getRootData()});var layoutInfo=this._layoutInfo;var ticksText=layoutInfo.ticksText;if(this.isDiscrete){if(this.useCompositeAxis){this._buildCompositeScene(rootScene)}else{layoutInfo.ticks.forEach(function(tickData,index){new pvc.visual.CartesianAxisTickScene(rootScene,{group:tickData,tick:tickData.value,tickRaw:tickData.rawValue,tickLabel:ticksText[index]})})}}else{layoutInfo.ticks.forEach(function(majorTick,index){new pvc.visual.CartesianAxisTickScene(rootScene,{tick:majorTick,tickRaw:majorTick,tickLabel:ticksText[index]})},this)}}return this._rootScene},_buildCompositeScene:function(rootScene){var isV1Compat=this.compatVersion()<=1;rootScene.vars.tick=new pvc.visual.ValueLabelVar('',"");recursive(rootScene);function recursive(scene){var data=scene.group;if(isV1Compat){var tickVar=scene.vars.tick;scene.nodeValue=scene.value=tickVar.rawValue;scene.nodeLabel=scene.label=tickVar.label}if(data.childCount()){data.children().each(function(childData){var childScene=new pvc.visual.CartesianAxisTickScene(scene,{group:childData,tick:childData.value,tickRaw:childData.rawValue,tickLabel:childData.label});recursive(childScene)})}}},_getRootData:function(){var chart=this.chart;var data=chart.data;if(this.isDiscrete&&this.useCompositeAxis){var orientation=this.anchor;var reverse=orientation=='bottom'||orientation=='left';data=chart.visualRoles(this.roleName).select(data,{visible:true,reverse:reverse})}return data},_getOrthoScale:function(){var orthoType=this.axis.type==='base'?'ortho':'base';return this.chart.axes[orthoType].scale},_getOrthoAxis:function(){var orthoType=this.axis.type==='base'?'ortho':'base';return this.chart.axes[orthoType]},renderOrdinalAxis:function(){var myself=this,scale=this.scale,hiddenLabelText=this.hiddenLabelText,anchorOpposite=this.anchorOpposite(),anchorLength=this.anchorLength(),anchorOrtho=this.anchorOrtho(),anchorOrthoLength=this.anchorOrthoLength(),layoutInfo=this._layoutInfo,pvRule=this.pvRule,ticks=layoutInfo.ticks,data=layoutInfo.data,itemCount=layoutInfo.ticks.length,rootScene=this._getRootScene(),includeModulo=this._tickIncludeModulo,isV1Compat=this.compatVersion()<=1;rootScene.vars.tickIncludeModulo=includeModulo;rootScene.vars.hiddenLabelText=hiddenLabelText;var wrapper;if(isV1Compat){var DataElement=function(tickVar){this.value=this.absValue=tickVar.rawValue;this.nodeName=''+(this.value||'');this.path=this.nodeName?[this.nodeName]:[];this.label=this.absLabel=tickVar.label};DataElement.prototype.toString=function(){return''+this.value};wrapper=function(v1f){return function(tickScene){var markWrapped=Object.create(this);markWrapped.index=this.parent.index;return v1f.call(markWrapped,new DataElement(tickScene.vars.tick))}}}var pvTicksPanel=new pvc.visual.Panel(this,this.pvPanel,{extensionId:'ticksPanel'}).lock('data',rootScene.childNodes).localProperty('hidden').lockMark('hidden',function(){return(this.index%includeModulo)!==0}).lock(anchorOpposite,0).lockMark(anchorOrtho,function(tickScene){return scale(tickScene.vars.tick.value)}).lock('strokeDasharray',null).lock('strokeStyle',null).lock('fillStyle',null).lock('lineWidth',0).pvMark.zOrder(20);if(isV1Compat||this.showTicks){var pvTicks=this.pvTicks=new pvc.visual.Rule(this,pvTicksPanel,{extensionId:'ticks',wrapper:wrapper}).lock('data').intercept('visible',function(){return!this.pvMark.parent.hidden()&&this.delegateExtension(true)}).optional('lineWidth',1).lock(anchorOpposite,0).lock(anchorOrtho,0).lock(anchorLength,null).optional(anchorOrthoLength,this.tickLength*2/3).override('defaultColor',function(type){if(isV1Compat){return pv.Color.names.transparent}return pvRule.scene?pvRule.scene[0].strokeStyle:"#666666"}).pvMark}var baseline;var align;switch(this.anchor){case'top':align='center';baseline='bottom';break;case'bottom':align='center';baseline='top';break;case'left':align='right';baseline='middle';break;case'right':align='left';baseline='middle';break}var font=this.font;var maxTextWidth=this._layoutInfo.maxTextWidth;if(!isFinite(maxTextWidth)){maxTextWidth=0}this.pvLabel=new pvc.visual.Label(this,pvTicksPanel,{extensionId:'label',noClick:false,noDoubleClick:false,noSelect:false,noTooltip:false,noHover:false,wrapper:wrapper,tooltipArgs:{buildTooltip:function(context){return context.scene.vars.tick.label},isLazy:false,options:{gravity:this._calcTipsyGravity()}}}).intercept('visible',function(tickScene){return!this.pvMark.parent.hidden()?this.delegateExtension(true):!!tickScene.vars.hiddenLabelText}).intercept('text',function(tickScene){var text;if(this.pvMark.parent.hidden()){text=tickScene.vars.hiddenLabelText}else{text=this.delegateExtension();if(text===undefined){text=tickScene.vars.tick.label}if(maxTextWidth){text=pvc.text.trimToWidthB(maxTextWidth,text,font,"..",false)}}return text}).pvMark.zOrder(40).lock(anchorOpposite,this.tickLength).lock(anchorOrtho,0).font(font).textStyle("#666666").textAlign(align).textBaseline(baseline);this._debugTicksPanel(pvTicksPanel)},_debugTicksPanel:function(pvTicksPanel){if(pvc.debug>=16){var corners=this._layoutInfo.labelBBox.source.points();if(corners.length>1){corners=corners.concat(corners[0])}pvTicksPanel.add(pv.Panel)[this.anchorOpposite()](this.tickLength)[this.anchorOrtho()](0)[this.anchorLength()](0)[this.anchorOrthoLength()](0).fillStyle(null).strokeStyle(null).lineWidth(0).add(pv.Line).visible(function(){var gp=this.parent.parent;return!gp.hidden||!gp.hidden()}).data(corners).left(function(p){return p.x}).top(function(p){return p.y}).strokeStyle('red').lineWidth(0.5).strokeDasharray('-')}},renderLinearAxis:function(){var scale=this.scale,orthoAxis=this._getOrthoAxis(),orthoScale=orthoAxis.scale,pvRule=this.pvRule,anchorOpposite=this.anchorOpposite(),anchorLength=this.anchorLength(),anchorOrtho=this.anchorOrtho(),anchorOrthoLength=this.anchorOrthoLength(),rootScene=this._getRootScene();var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(tickScene){var markWrapped=Object.create(this);markWrapped.index=this.parent.index;return v1f.call(markWrapped,tickScene.vars.tick.rawValue)}}}var pvTicksPanel=new pvc.visual.Panel(this,this.pvPanel,{extensionId:'ticksPanel'}).lock('data',rootScene.childNodes).lock(anchorOpposite,0).lockMark(anchorOrtho,function(tickScene){return scale(tickScene.vars.tick.value)}).lock('strokeStyle',null).lock('fillStyle',null).lock('lineWidth',0).pvMark.zOrder(20);if(this.showTicks){var pvTicks=this.pvTicks=new pvc.visual.Rule(this,pvTicksPanel,{extensionId:'ticks',wrapper:wrapper}).lock('data').override('defaultColor',function(){return pvRule.scene?pvRule.scene[0].strokeStyle:"#666666"}).lock(anchorOpposite,0).lock(anchorOrtho,0).lock(anchorLength,null).optional(anchorOrthoLength,this.tickLength).pvMark;if(this.showMinorTicks){var layoutInfo=this._layoutInfo;var ticks=layoutInfo.ticks;var tickCount=ticks.length;var minorTickOffset=tickCount>1?Math.abs(scale(ticks[1])-scale(ticks[0]))/2:0;this.pvMinorTicks=new pvc.visual.Rule(this,this.pvTicks,{extensionId:'minorTicks',wrapper:wrapper}).lock('data').intercept('visible',function(){var visible=(this.index=rootPanel.width()){return'right'}}return'center'})}else{label.textAlign(anchorOpposite).textBaseline(function(tickScene){var absTop;if(this.index===0){absTop=label.toScreenTransform().transformVPosition(label.top());if(absTop>=rootPanel.height()){return'bottom'}}else if(this.index===tickScene.parent.childNodes.length-1){absTop=label.toScreenTransform().transformVPosition(label.top());if(absTop<=0){return'top'}}return'middle'})}},_onV1Click:function(context,handler){if(this.isDiscrete&&this.useCompositeAxis){handler.call(context.pvMark,context.scene,context.event)}},_onV1DoubleClick:function(context,handler){if(this.isDiscrete&&this.useCompositeAxis){handler.call(context.pvMark,context.scene,context.event)}},_getSelectableMarks:function(){if(this.isDiscrete&&this.isVisible&&this.pvLabel){return[this.pvLabel]}},renderCompositeOrdinalAxis:function(){var myself=this,isTopOrBottom=this.isAnchorTopOrBottom(),axisDirection=isTopOrBottom?'h':'v',diagDepthCutoff=2,vertDepthCutoff=2,font=this.font;var diagMargin=pv.Text.fontHeight(font)/2;var layout=this._pvLayout=this.getLayoutSingleCluster();layout.node.def("fitInfo",null).height(function(tickScene,e,f){var fitInfo=pvc.text.getFitInfo(tickScene.dx,tickScene.dy,tickScene.vars.tick.label,font,diagMargin);if(!fitInfo.h){if(axisDirection==='v'&&fitInfo.v){vertDepthCutoff=Math.min(diagDepthCutoff,tickScene.depth)}else{diagDepthCutoff=Math.min(diagDepthCutoff,tickScene.depth)}}this.fitInfo(fitInfo);return tickScene.dy});layout.node.add(pv.Bar).fillStyle('rgba(127,127,127,.001)').strokeStyle(function(tickScene){if(tickScene.maxDepth===1||!tickScene.maxDepth){return null}return"rgba(127,127,127,0.3)"}).lineWidth(function(tickScene){if(tickScene.maxDepth===1||!tickScene.maxDepth){return 0}return 0.5}).text(function(tickScene){return tickScene.vars.tick.label});var H_CUTOFF_ANG=0.30,V_CUTOFF_ANG=1.27;var align=isTopOrBottom?"center":(this.anchor=="left")?"right":"left";var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(tickScene){return v1f.call(this,tickScene)}}}this.pvLabel=new pvc.visual.Label(this,layout.label,{extensionId:'label',noClick:false,noDoubleClick:false,noSelect:false,noTooltip:false,noHover:false,wrapper:wrapper,tooltipArgs:{isLazy:false,buildTooltip:function(context){return context.scene.vars.tick.label},options:{gravity:this._calcTipsyGravity(),offset:diagMargin*2}}}).pvMark.def('lblDirection','h').textAngle(function(tickScene){if(tickScene.depth>=vertDepthCutoff&&tickScene.depth=diagDepthCutoff){var tan=tickScene.dy/tickScene.dx;var angle=Math.atan(tan);if(angle>V_CUTOFF_ANG){this.lblDirection('v');return-Math.PI/2}if(angle>H_CUTOFF_ANG){this.lblDirection('d');return-angle}}this.lblDirection('h');return 0}).textMargin(1).textAlign(function(tickScene){return(axisDirection!='v'||tickScene.depth>=vertDepthCutoff||tickScene.depth>=diagDepthCutoff)?'center':align}).left(function(tickScene){return(axisDirection!='v'||tickScene.depth>=vertDepthCutoff||tickScene.depth>=diagDepthCutoff)?tickScene.x+tickScene.dx/2:((align=='right')?tickScene.x+tickScene.dx:tickScene.x)}).font(font).textStyle("#666666").text(function(tickScene){var fitInfo=this.fitInfo();var label=tickScene.vars.tick.label;switch(this.lblDirection()){case'h':if(!fitInfo.h){return pvc.text.trimToWidth(tickScene.dx,label,font,'..')}break;case'v':if(!fitInfo.v){return pvc.text.trimToWidth(tickScene.dy,label,font,'..')}break;case'd':if(!fitInfo.d){var diagonalLength=Math.sqrt(tickScene.dy*tickScene.dy+tickScene.dx*tickScene.dx);return pvc.text.trimToWidth(diagonalLength-diagMargin,label,font,'..')}break}return label})},getLayoutSingleCluster:function(){var rootScene=this._getRootScene(),orientation=this.anchor,maxDepth=rootScene.group.treeHeight,depthLength=this._layoutInfo.axisSize;maxDepth++;var baseDisplacement=depthLength/maxDepth,margin=maxDepth>2?((1/12)*depthLength):0;baseDisplacement-=margin;var scaleFactor=maxDepth/(maxDepth-1),orthoLength=pvc.BasePanel.orthogonalLength[orientation];var displacement=(orthoLength=='width')?(orientation==='left'?[-baseDisplacement,0]:[baseDisplacement,0]):(orientation==='top'?[0,-baseDisplacement]:[0,baseDisplacement]);this.pvRule.sign.override('defaultColor',def.fun.constant(null)).override('defaultStrokeWidth',def.fun.constant(0));var panel=this.pvRule.add(pv.Panel)[orthoLength](depthLength).strokeStyle(null).lineWidth(0).add(pv.Panel)[orthoLength](depthLength*scaleFactor).strokeStyle(null).lineWidth(0);panel.transform(pv.Transform.identity.translate(displacement[0],displacement[1]));return panel.add(pv.Layout.Cluster.Fill).nodes(rootScene.nodes()).orient(orientation)},_calcTipsyGravity:function(){switch(this.anchor){case'bottom':return's';case'top':return'n';case'left':return'w';case'right':return'e'}return's'}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcAxisTitlePanel.js b/pacotes/ccc2/compacto/pvcAxisTitlePanel.js deleted file mode 100755 index b3e6e90..0000000 --- a/pacotes/ccc2/compacto/pvcAxisTitlePanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.AxisTitlePanel',pvc.TitlePanelAbstract).init(function(chart,parent,axis,options){this.axis=axis;this.base(chart,parent,options);this._extensionPrefix=axis.extensionPrefixes.map(function(prefix){return prefix+'Title'})}).add({_calcLayout:function(layoutInfo){var scale=this.axis.scale;if(!scale||scale.isNull){return new pvc.Size(0,0)}return this.base(layoutInfo)},_createCore:function(layoutInfo){var scale=this.axis.scale;if(!scale||scale.isNull){return}return this.base(layoutInfo)}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBarAbstract.js b/pacotes/ccc2/compacto/pvcBarAbstract.js deleted file mode 100755 index f6fbd6a..0000000 --- a/pacotes/ccc2/compacto/pvcBarAbstract.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.BarAbstract',pvc.CategoricalAbstract).init(function(options){this.base(options);var parent=this.parent;if(parent){this._valueRole=parent._valueRole}}).add({_initVisualRoles:function(){this.base();this._addVisualRole('value',{isMeasure:true,isRequired:true,isPercent:this.options.stacked,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:'value'});this._valueRole=this.visualRoles('value')},_getCategoryRoleSpec:function(){var catRoleSpec=this.base();catRoleSpec.requireIsDiscrete=true;return catRoleSpec},_initData:function(){this.base.apply(this,arguments);var data=this.data;this._valueDim=data.dimensions(this._valueRole.firstDimensionName())}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBarAbstractPanel.js b/pacotes/ccc2/compacto/pvcBarAbstractPanel.js deleted file mode 100755 index e9ed931..0000000 --- a/pacotes/ccc2/compacto/pvcBarAbstractPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.BarAbstractPanel',pvc.CategoricalAbstractPanel).add({pvBar:null,pvBarLabel:null,pvCategoryPanel:null,pvSecondLine:null,pvSecondDot:null,_creating:function(){var groupScene=this.defaultVisibleBulletGroupScene();if(groupScene&&!groupScene.hasRenderer()){var colorAxis=groupScene.colorAxis;var drawLine=colorAxis.option('LegendDrawLine');var drawMarker=!drawLine||colorAxis.option('LegendDrawMarker');if(drawMarker){var keyArgs={drawMarker:true,markerShape:colorAxis.option('LegendShape'),drawRule:drawLine,markerPvProto:new pv.Mark()};this.extend(keyArgs.markerPvProto,'',{constOnly:true});groupScene.renderer(new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs))}}},_createCore:function(){this.base();var me=this,chart=me.chart,plot=me.plot,isStacked=!!me.stacked,isVertical=me.isOrientationVertical(),data=me.visibleData(),seriesData=me.visualRoles.series.flatten(data),rootScene=me._buildScene(data,seriesData),orthoAxis=me.axes.ortho,baseAxis=me.axes.base,orthoScale=orthoAxis.scale,orthoZero=orthoScale(0),sceneOrthoScale=orthoAxis.sceneScale({sceneVarName:'value',nullToZero:false}),sceneBaseScale=baseAxis.sceneScale({sceneVarName:'category'}),barSizeRatio=plot.option('BarSizeRatio'),barSizeMax=plot.option('BarSizeMax'),barStackedMargin=plot.option('BarStackedMargin'),baseRange=baseAxis.scale.range(),bandWidth=baseRange.band,barStepWidth=baseRange.step,barWidth,reverseSeries=isVertical===isStacked;if(isStacked){barWidth=bandWidth}else{var S=seriesData.childCount();barWidth=S>0?(bandWidth*barSizeRatio/S):0}if(barWidth>barSizeMax){barWidth=barSizeMax}me.barWidth=barWidth;me.barStepWidth=barStepWidth;var wrapper;if(me.compatVersion()<=1){wrapper=function(v1f){return function(scene){var markParent=Object.create(this.parent);var mark=Object.create(this);mark.parent=markParent;var serIndex=scene.parent.childIndex();var catIndex=scene.childIndex();if(isStacked){markParent.index=serIndex;mark.index=catIndex}else{markParent.index=catIndex;mark.index=serIndex}return v1f.call(mark,scene.vars.value.rawValue)}}}me.pvBarPanel=new pvc.visual.Panel(me,me.pvPanel,{panelType:pv.Layout.Band,extensionId:'panel'}).lock('layers',rootScene.childNodes).lockMark('values',function(seriesScene){return seriesScene.childNodes}).lockMark('orient',isVertical?'bottom-left':'left-bottom').lockMark('layout',isStacked?'stacked':'grouped').lockMark('verticalMode',me._barVerticalMode()).lockMark('yZero',orthoZero).pvMark.band.x(sceneBaseScale).w(bandWidth).differentialControl(me._barDifferentialControl()).item.order(reverseSeries?"reverse":null).h(function(scene){var y=sceneOrthoScale(scene);return y!=null?chart.animate(0,y-orthoZero):null}).w(barWidth).horizontalRatio(barSizeRatio).verticalMargin(barStackedMargin).end;this.pvBar=new pvc.visual.Bar(me,me.pvBarPanel.item,{extensionId:'',freePosition:true,wrapper:wrapper}).lockDimensions().pvMark.antialias(false);if(plot.option('OverflowMarkersVisible')){this._addOverflowMarkers(wrapper)}if(me.valuesVisible){me.pvBarLabel=new pvc.visual.Label(me,me.pvBar.anchor(me.valuesAnchor||'center'),{extensionId:'label',wrapper:wrapper}).pvMark.visible(function(){var length=this.scene.target[this.index][isVertical?'height':'width'];return length>=4}).font(me.valuesFont).text(function(scene){return scene.format(me.valuesMask)})}},_barVerticalMode:function(){return null},_barDifferentialControl:function(){return null},_getV1Datum:function(scene){var datum=scene.datum;if(datum){var datumEx=Object.create(datum);datumEx.percent=scene.vars.value.percent;datum=datumEx}return datum},_addOverflowMarkers:function(wrapper){var orthoAxis=this.axes.ortho;if(orthoAxis.option('FixedMax')!=null){this.pvOverflowMarker=this._addOverflowMarker(false,orthoAxis.scale,wrapper)}if(orthoAxis.option('FixedMin')!=null){this.pvUnderflowMarker=this._addOverflowMarker(true,orthoAxis.scale,wrapper)}},_addOverflowMarker:function(isMin,orthoScale,wrapper){var isVertical=this.isOrientationVertical(),a_bottom=isVertical?"bottom":"left",a_top=this.anchorOpposite(a_bottom),a_height=this.anchorOrthoLength(a_bottom),a_width=this.anchorLength(a_bottom),paddings=this._layoutInfo.paddings,rOrthoBound=isMin?(orthoScale.min-paddings[a_bottom]):(orthoScale.max+paddings[a_top]),angle;if(!isMin){angle=isVertical?Math.PI:-Math.PI/2}else{angle=isVertical?0:Math.PI/2}return new pvc.visual.Dot(this,this.pvBar.anchor('center'),{noSelect:true,noHover:true,noClick:true,noDoubleClick:true,noTooltip:true,freePosition:true,extensionId:isMin?'underflowMarker':'overflowMarker',wrapper:wrapper}).intercept('visible',function(scene){var visible=this.delegateExtension();if(visible!==undefined&&!visible){return false}var value=scene.vars.value.value;if(value==null){return false}var targetInstance=this.pvMark.scene.target[this.index];var orthoMaxPos=targetInstance[a_bottom]+(value>0?targetInstance[a_height]:0);return isMin?(orthoMaxPosrOrthoBound)}).lock(a_top,null).lock('shapeSize').pvMark.shape("triangle").shapeRadius(function(){return Math.min(Math.sqrt(10),this.scene.target[this.index][a_width]/2)}).shapeAngle(angle).lineWidth(1.5).strokeStyle("red").fillStyle("white")[a_bottom](function(){return rOrthoBound+(isMin?1:-1)*(this.shapeRadius()+2)})},renderInteractive:function(){this.pvPanel.render()},_getSelectableMarks:function(){return[this.pvBar]},_buildScene:function(data,seriesData){var rootScene=new pvc.visual.Scene(null,{panel:this,group:data});var categDatas=data._children;var roles=this.visualRoles;var valueVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.value,{hasPercentSubVar:this.stacked});var colorVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.color);seriesData.children().each(createSeriesScene);return rootScene;function createSeriesScene(seriesData1){var seriesScene=new pvc.visual.Scene(rootScene,{group:seriesData1}),seriesKey=seriesData1.key;seriesScene.vars.series=pvc.visual.ValueLabelVar.fromComplex(seriesData1);colorVarHelper.onNewScene(seriesScene,false);categDatas.forEach(function(categData1){var group=data._childrenByKey[categData1.key]._childrenByKey[seriesKey],scene=new pvc.visual.Scene(seriesScene,{group:group});var categVar=scene.vars.category=pvc.visual.ValueLabelVar.fromComplex(categData1);categVar.group=categData1;valueVarHelper.onNewScene(scene,true);colorVarHelper.onNewScene(scene,true)})}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBarChart.js b/pacotes/ccc2/compacto/pvcBarChart.js deleted file mode 100755 index 7f04c9e..0000000 --- a/pacotes/ccc2/compacto/pvcBarChart.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.BarChart',pvc.BarAbstract).add({_animatable:true,_allowV1SecondAxis:true,_initPlotsCore:function(){var options=this.options;var barPlot=new pvc.visual.BarPlot(this);var trend=barPlot.option('Trend');if(options.plot2){var plot2Plot=new pvc.visual.PointPlot(this,{name:'plot2',fixed:{DataPart:'1'},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:true}});if(!trend){trend=plot2Plot.option('Trend')}}if(trend){new pvc.visual.PointPlot(this,{name:'trend',fixed:{DataPart:'trend',TrendType:'none',ColorRole:'series',NullInterpolatioMode:'none'},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:false}})}},_hasDataPartRole:function(){return true},_createPlotPanels:function(parentPanel,baseOptions){var plots=this.plots;var barPlot=plots.bar;var barPanel=new pvc.BarPanel(this,parentPanel,barPlot,Object.create(baseOptions));this.barChartPanel=barPanel;var plot2Plot=plots.plot2;if(plot2Plot){if(pvc.debug>=3){this._log("Creating Point panel.")}var pointPanel=new pvc.PointPanel(this,parentPanel,plot2Plot,Object.create(baseOptions));barPanel.pvSecondLine=pointPanel.pvLine;barPanel.pvSecondDot=pointPanel.pvDot;pointPanel._applyV1BarSecondExtensions=true}var trendPlot=plots.trend;if(trendPlot){if(pvc.debug>=3){this._log("Creating Trends Point panel.")}new pvc.PointPanel(this,parentPanel,trendPlot,Object.create(baseOptions))}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBarPanel.js b/pacotes/ccc2/compacto/pvcBarPanel.js deleted file mode 100755 index db172ab..0000000 --- a/pacotes/ccc2/compacto/pvcBarPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.BarPanel',pvc.BarAbstractPanel).add({}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBaseChart.axes.js b/pacotes/ccc2/compacto/pvcBaseChart.axes.js deleted file mode 100755 index 16335f2..0000000 --- a/pacotes/ccc2/compacto/pvcBaseChart.axes.js +++ /dev/null @@ -1 +0,0 @@ -pvc.BaseChart.add({colors:null,axes:null,axesList:null,axesByType:null,_axisClassByType:{'color':pvc.visual.ColorAxis,'size':pvc.visual.SizeAxis,'base':pvc.visual.CartesianAxis,'ortho':pvc.visual.CartesianAxis},_axisCreateWhere:{'color':1,'size':2,'base':3,'ortho':3},_axisCreationOrder:['color','size','base','ortho'],_axisCreateIfUnbound:{},_initAxes:function(hasMultiRole){this.axes={};this.axesList=[];this.axesByType={};delete this._rolesColorScale;var dataCellsByAxisTypeThenIndex;if(!this.parent){dataCellsByAxisTypeThenIndex={};this.plotList.forEach(function(plot){this._collectPlotAxesDataCells(plot,dataCellsByAxisTypeThenIndex)},this);this._fixTrendsLabel(dataCellsByAxisTypeThenIndex)}else{dataCellsByAxisTypeThenIndex=this.root._dataCellsByAxisTypeThenIndex}this._dataCellsByAxisTypeThenIndex=dataCellsByAxisTypeThenIndex;var here=0;if(!this.parent){here|=1}if(this.parent||!hasMultiRole){here|=2}this._axisCreateHere=here;this._axisCreationOrder.forEach(function(type){if((this._axisCreateWhere[type]&here)!==0){var AxisClass;var dataCellsByAxisIndex=dataCellsByAxisTypeThenIndex[type];if(dataCellsByAxisIndex){AxisClass=this._axisClassByType[type];if(AxisClass){dataCellsByAxisIndex.forEach(function(dataCells,axisIndex){new AxisClass(this,type,axisIndex)},this)}}else if(this._axisCreateIfUnbound[type]){AxisClass=this._axisClassByType[type];if(AxisClass){new AxisClass(this,type,0)}}}},this);if(this.parent){this.root.axesList.forEach(function(axis){if(!def.hasOwn(this.axes,axis.id)){this._addAxis(axis)}},this)}},_fixTrendsLabel:function(dataCellsByAxisTypeThenIndex){var dataPartDimName=this._getDataPartDimName();if(dataPartDimName){var firstDataCell=def.query(def.ownKeys(dataCellsByAxisTypeThenIndex)).selectMany(function(axisType){return dataCellsByAxisTypeThenIndex[axisType]}).selectMany().first(function(dataCell){return!!dataCell.trend});if(firstDataCell){var trendInfo=pvc.trends.get(firstDataCell.trend.type);var dataPartAtom=trendInfo.dataPartAtom;var trendLabel=firstDataCell.trend.label;if(trendLabel===undefined){trendLabel=dataPartAtom.f}this._firstTrendAtomProto={v:dataPartAtom.v,f:trendLabel}}else{delete this._firstTrendAtomProto}}},_addAxis:function(axis){this.axes[axis.id]=axis;if(axis.chart===this){axis.axisIndex=this.axesList.length}this.axesList.push(axis);var typeAxes=def.array.lazy(this.axesByType,axis.type);var typeIndex=typeAxes.count||0;axis.typeIndex=typeIndex;typeAxes[axis.index]=axis;if(!typeIndex){typeAxes.first=axis}typeAxes.count=typeIndex+1;if(axis.type==='color'&&axis.isBound()){this._onColorAxisScaleSet(axis)}return this},_getAxis:function(type,index){var typeAxes=this.axesByType[type];if(typeAxes&&index!=null&&(+index>=0)){return typeAxes[index]}},_bindAxes:function(){var here=this._axisCreateHere;def.eachOwn(this._dataCellsByAxisTypeThenIndex,function(dataCellsByAxisIndex,type){if((this._axisCreateWhere[type]&here)!==0){dataCellsByAxisIndex.forEach(function(dataCells,index){var axisId=pvc.buildIndexedId(type,index);var axis=this.axes[axisId];if(!axis.isBound()){axis.bind(dataCells)}},this)}},this)},_setAxesScales:function(){if(!this.parent){var colorAxes=this.axesByType.color;if(colorAxes){colorAxes.forEach(function(axis){if(axis.isBound()){axis.calculateScale();this._onColorAxisScaleSet(axis)}},this)}}},_onColorAxisScaleSet:function(axis){switch(axis.index){case 0:this.colors=axis.scheme();break;case 1:if(this._allowV1SecondAxis){this.secondAxisColor=axis.scheme()}break}},_getRoleColorScale:function(roleName){return def.lazy(def.lazy(this,'_rolesColorScale'),roleName,this._createRoleColorScale,this)},_createRoleColorScale:function(roleName){var firstScale,scale;var valueToColorMap={};this.axesByType.color.forEach(function(axis){var axisRole=axis.role;var isRoleCompatible=(axisRole.name===roleName)||(axisRole.sourceRole&&axisRole.sourceRole.name===roleName);if(isRoleCompatible&&axis.scale&&(axis.index===0||axis.option.isSpecified('Colors')||axis.option.isSpecified('Map'))){scale=axis.scale;if(!firstScale){firstScale=scale}axis.domainValues.forEach(addDomainValue)}},this);function addDomainValue(value){var key=''+value;if(!def.hasOwnProp.call(valueToColorMap,key)){valueToColorMap[key]=scale(value)}}if(!firstScale){return pvc.createColorScheme()()}scale=function(value){var key=''+value;if(def.hasOwnProp.call(valueToColorMap,key)){return valueToColorMap[key]}var color=firstScale(value);valueToColorMap[key]=color;return color};def.copy(scale,firstScale);return scale},_onLaidOut:function(){}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBaseChart.data.js b/pacotes/ccc2/compacto/pvcBaseChart.data.js deleted file mode 100755 index 8ed9073..0000000 --- a/pacotes/ccc2/compacto/pvcBaseChart.data.js +++ /dev/null @@ -1 +0,0 @@ -pvc.BaseChart.add({dataEngine:null,data:null,_partData:null,_visibleDataCache:null,resultset:[],metadata:[],_constructData:function(options){var parent=this.parent;if(parent){this.dataEngine=this.data=options.data||def.fail.argumentRequired('options.data')}},_checkNoDataI:function(){if(!this.parent){if(!this.allowNoData&&this.resultset.length===0){throw new NoDataException()}}},_checkNoDataII:function(){if(!this.parent){if(!this.allowNoData&&(!this.data||!this.data.count())){throw new NoDataException()}}},_initData:function(keyArgs){if(!this.parent){var data=this.data;if(!data||def.get(keyArgs,'reloadData',true)){this._onLoadData()}else{data.clearVirtuals();data.disposeChildren()}}delete this._partData;delete this._visibleDataCache;if(pvc.debug>=3){this._log(this.data.getInfo())}},_onLoadData:function(){var data=this.data;var options=this.options;var dataPartDimName=this._getDataPartDimName();var complexTypeProj=this._complexTypeProj;var translOptions=this._createTranslationOptions(dataPartDimName);var translation=this._createTranslation(translOptions);if(pvc.debug>=3){translation.logSource()}if(!data){translation.configureType();if(dataPartDimName&&!complexTypeProj.isReadOrCalc(dataPartDimName)){this._addDefaultDataPartCalculation(dataPartDimName)}}this._bindVisualRolesPostI();var complexType;if(!data){complexType=new pvc.data.ComplexType();complexTypeProj.configureComplexType(complexType,translOptions)}else{complexType=data.type}this._bindVisualRolesPostII(complexType);if(pvc.debug>=10){this._log(complexType.describe())}if(pvc.debug>=3){this._logVisualRoles()}if(!data){data=this.dataEngine=this.data=new pvc.data.Data({type:complexType,labelSep:options.groupedLabelSep})}var loadKeyArgs={where:this._getLoadFilter(),isNull:this._getIsNullDatum()};var resultQuery=translation.execute(data);data.load(resultQuery,loadKeyArgs)},_createComplexTypeProject:function(){var options=this.options;var complexTypeProj=new pvc.data.ComplexTypeProject(options.dimensionGroups);var userDimsSpec=options.dimensions;for(var dimName in userDimsSpec){complexTypeProj.setDim(dimName,userDimsSpec[dimName])}var dataPartDimName=this._getDataPartDimName();if(dataPartDimName){complexTypeProj.setDim(dataPartDimName);this._addPlot2SeriesDataPartCalculation(complexTypeProj,dataPartDimName)}var calcSpecs=options.calculations;if(calcSpecs){calcSpecs.forEach(function(calcSpec){complexTypeProj.setCalc(calcSpec)})}return complexTypeProj},_getLoadFilter:function(){if(this.options.ignoreNulls){var me=this;return function(datum){var isNull=datum.isNull;if(isNull&&pvc.debug>=4){me._info("Datum excluded.")}return!isNull}}},_getIsNullDatum:function(){var measureDimNames=this.measureDimensionsNames(),M=measureDimNames.length;if(M){return function(datum){var atoms=datum.atoms;for(var i=0;i1){return this._partData.where([def.set({},dataPartDimName,dataPartValues)])}dataPartValues=dataPartValues[0]}var child=this._partData._childrenByKey[dataPartValues+''];if(!child){var dataPartCell={v:dataPartValues};if(dataPartValues==='trend'){var firstTrendAtom=this._firstTrendAtomProto;if(firstTrendAtom){dataPartCell.f=firstTrendAtom.f}}child=new pvc.data.Data({parent:this._partData,atoms:def.set({},dataPartDimName,dataPartCell),dimNames:[dataPartDimName],datums:[]})}return child},visibleData:function(dataPartValue,keyArgs){var ignoreNulls=def.get(keyArgs,'ignoreNulls',true);if(ignoreNulls&&this.options.ignoreNulls){ignoreNulls=false}keyArgs=keyArgs?Object.create(keyArgs):{};keyArgs.ignoreNulls=ignoreNulls;var key=ignoreNulls+'|'+dataPartValue,data=def.getOwn(this._visibleDataCache,key);if(!data){data=this._createVisibleData(dataPartValue,keyArgs);if(data){(this._visibleDataCache||(this._visibleDataCache={}))[key]=data}}return data},_createVisibleData:function(dataPartValue,keyArgs){var partData=this.partData(dataPartValue);if(!partData){return null}var ignoreNulls=def.get(keyArgs,'ignoreNulls');return this._serRole&&this._serRole.grouping?partData.flattenBy(this._serRole,{visible:true,isNull:ignoreNulls?false:null}):partData},_generateTrends:function(){if(this._dataPartRole){def.query(def.own(this.axes)).selectMany(function(axis){return axis.dataCells}).where(function(dataCell){return!!dataCell.trend}).distinct(function(dataCell){return dataCell.role.name+'|'+(dataCell.dataPartValue||'')}).each(this._generateTrendsDataCell,this)}},_interpolate:function(){def.query(def.own(this.axes)).selectMany(function(axis){return axis.dataCells}).where(function(dataCell){var nim=dataCell.nullInterpolationMode;return!!nim&&nim!=='none'}).distinct(function(dataCell){return dataCell.role.name+'|'+(dataCell.dataPartValue||'')}).each(this._interpolateDataCell,this)},_interpolateDataCell:function(dataCell){},_generateTrendsDataCell:function(dataCell){},setData:function(data,options){this.setResultset(data.resultset);this.setMetadata(data.metadata);$.extend(this.options,options);return this},setResultset:function(resultset){!this.parent||def.fail.operationInvalid("Can only set resultset on root chart.");this.resultset=resultset;if(!resultset.length){this._log("Warning: Resultset is empty")}return this},setMetadata:function(metadata){!this.parent||def.fail.operationInvalid("Can only set resultset on root chart.");this.metadata=metadata;if(!metadata.length){this._log("Warning: Metadata is empty")}return this}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBaseChart.extension.js b/pacotes/ccc2/compacto/pvcBaseChart.extension.js deleted file mode 100755 index d7fa1a5..0000000 --- a/pacotes/ccc2/compacto/pvcBaseChart.extension.js +++ /dev/null @@ -1 +0,0 @@ -pvc.BaseChart.add({_processExtensionPoints:function(){var components;if(!this.parent){var points=this.options.extensionPoints;components={};if(points){for(var p in points){var id,prop;var splitIndex=p.indexOf("_");if(splitIndex>0){id=p.substring(0,splitIndex);prop=p.substr(splitIndex+1);if(id&&prop){var component=def.getOwn(components,id)||(components[id]=new def.OrderedMap());component.add(prop,points[p])}}}}}else{components=this.parent._components}this._components=components},extend:function(mark,ids,keyArgs){if(def.array.is(ids)){ids.forEach(function(id){this._extendCore(mark,id,keyArgs)},this)}else{this._extendCore(mark,ids,keyArgs)}},_extendCore:function(mark,id,keyArgs){if(mark){var component=def.getOwn(this._components,id);if(component){if(mark.borderPanel){mark=mark.borderPanel}var logOut=pvc.debug>=3?[]:null;var constOnly=def.get(keyArgs,'constOnly',false);var wrap=mark.wrap;var keyArgs2={tag:pvc.extensionTag};var isRealMark=mark instanceof pv.Mark;component.forEach(function(v,m){if(mark.isLocked&&mark.isLocked(m)){if(logOut){logOut.push(m+": locked extension point!")}}else if(mark.isIntercepted&&mark.isIntercepted(m)){if(logOut){logOut.push(m+":"+pvc.stringify(v)+" (controlled)")}}else{if(logOut){logOut.push(m+": "+pvc.stringify(v))}if(v!=null){var type=typeof v;if(type==='object'){if(m==='svg'||m==='css'){var v2=mark.propertyValue(m);if(v2){v=def.copy(v2,v)}}}else if(isRealMark&&(wrap||constOnly)&&type==='function'){if(constOnly){return}if(m!=='add'){v=wrap.call(mark,v,m)}}}if(typeof mark[m]==="function"){if(m!='add'&&mark.intercept){mark.intercept(m,v,keyArgs2)}else{mark[m](v)}}else{mark[m]=v}}});if(logOut){if(logOut.length){this._log("Applying Extension Points for: '"+id+"'\n\t* "+logOut.join("\n\t* "))}else if(pvc.debug>=5){this._log("No Extension Points for: '"+id+"'")}}}}else if(pvc.debug>=4){this._log("Applying Extension Points for: '"+id+"' (target mark does not exist)")}},_getExtension:function(id,prop){var component;if(!def.array.is(id)){component=def.getOwn(this._components,id);if(component){return component.get(prop)}}else{var i=id.length-1,value;while(i>=0){component=def.getOwn(this._components,id[i--]);if(component&&(value=component.get(prop))!==undefined){return value}}}},_getConstantExtension:function(id,prop){var value=this._getExtension(id,prop);if(!def.fun.is(value)){return value}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBaseChart.js b/pacotes/ccc2/compacto/pvcBaseChart.js deleted file mode 100755 index 80aea7a..0000000 --- a/pacotes/ccc2/compacto/pvcBaseChart.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.BaseChart',pvc.Abstract).init(function(options){var originalOptions=options;var parent=this.parent=def.get(options,'parent')||null;if(parent){options||def.fail.argumentRequired('options')}else{options=def.mixin.copy({},this.defaults,options)}this.options=options;if(parent){this.root=parent.root;this.smallColIndex=options.smallColIndex;this.smallRowIndex=options.smallRowIndex;this._tooltipEnabled=parent._tooltipEnabled;this._tooltipOptions=parent._tooltipOptions}else{this.root=this}this.base();if(pvc.debug>=3){this._info("NEW CHART\n"+pvc.logSeparator.replace(/-/g,'=')+"\n DebugLevel: "+pvc.debug)}if(pvc.debug>=3&&!parent&&originalOptions){this._info("OPTIONS:\n",originalOptions);if(pvc.debug>=5){this._trace(pvc.stringify(options,{ownOnly:false,funs:true}))}}if(parent){parent._addChild(this)}this._constructData(options);this._constructVisualRoles(options)}).add({_disposed:false,_animatable:false,parent:null,children:null,root:null,isPreRendered:false,_createVersion:0,renderCallback:undefined,multiChartPageCount:null,multiChartPageIndex:null,left:0,top:0,width:null,height:null,margins:null,paddings:null,_allowV1SecondAxis:false,compatVersion:function(options){return(options||this.options).compatVersion},_createLogInstanceId:function(){return""+this.constructor+this._createLogChildSuffix()},_createLogChildSuffix:function(){return this.parent?(" ("+(this.smallRowIndex+1)+","+(this.smallColIndex+1)+")"):""},_addChild:function(childChart){(childChart.parent===this)||def.assert("Not a child of this chart.");this.children.push(childChart)},_preRender:function(keyArgs){this._preRenderPhase1(keyArgs);this._preRenderPhase2(keyArgs)},_preRenderPhase1:function(keyArgs){this._createVersion++;this.isPreRendered=false;if(pvc.debug>=3){this._log("Prerendering")}this.children=[];if(!this.parent){pvc.removeTipsyLegends()}this._processOptions();this._checkNoDataI();if(!this.parent&&this._createVersion===1){this._initVisualRoles();this._bindVisualRolesPreI();this._complexTypeProj=this._createComplexTypeProject();this._bindVisualRolesPreII()}this._initData(keyArgs);this._checkNoDataII();var hasMultiRole=this._isRoleAssigned('multiChart');this._initPlots(hasMultiRole);this._initAxes(hasMultiRole);this._bindAxes(hasMultiRole);if(this.parent||!hasMultiRole){this._interpolate(hasMultiRole);this._generateTrends(hasMultiRole)}this._setAxesScales(hasMultiRole)},_preRenderPhase2:function(){var hasMultiRole=this._isRoleAssigned('multiChart');this._initChartPanels(hasMultiRole);this.isPreRendered=true},_setSmallLayout:function(keyArgs){if(keyArgs){var basePanel=this.basePanel;if(this._setProp('left',keyArgs)|this._setProp('top',keyArgs)){if(basePanel){def.set(basePanel.position,'left',this.left,'top',this.top)}}if(this._setProp('width',keyArgs)|this._setProp('height',keyArgs)){if(basePanel){basePanel.size=new pvc.Size(this.width,this.height)}}if(this._setProp('margins',keyArgs)&&basePanel){basePanel.margins=new pvc.Sides(this.margins)}if(this._setProp('paddings',keyArgs)&&basePanel){basePanel.paddings=new pvc.Sides(this.paddings)}}},_setProp:function(p,keyArgs){var v=keyArgs[p];if(v!=null){this[p]=v;return true}},_processOptions:function(){var options=this.options;if(parseInt(options.width,10)+"%"==options.width){try{var viewportwidth,viewportheight,wdiv,r,scr=null,inn=null,wNoScroll=0,wScroll=0;if(typeof window.innerWidth!='undefined'){viewportwidth=window.innerWidth,viewportheight=window.innerHeight}else if(typeof document.documentElement!='undefined'&&typeof document.documentElement.clientWidth!='undefined'&&document.documentElement.clientWidth!=0){viewportwidth=document.documentElement.clientWidth,viewportheight=document.documentElement.clientHeight}else{viewportwidth=document.getElementsByTagName('body')[0].clientWidth,viewportheight=document.getElementsByTagName('body')[0].clientHeight}scr=document.createElement('div');scr.style.position='absolute';scr.style.top='-1000px';scr.style.left='-1000px';scr.style.width='100px';scr.style.height='50px';scr.style.overflow='hidden';inn=document.createElement('div');inn.style.width='100%';inn.style.height='200px';scr.appendChild(inn);document.body.appendChild(scr);wNoScroll=inn.offsetWidth;scr.style.overflow='auto';wScroll=inn.offsetWidth;document.body.removeChild(document.body.lastChild);viewportwidth=viewportwidth-wNoScroll-wScroll;r=(parseInt(options.width,10)/100)*viewportwidth;options.width=parseInt(r,10)}catch(e){options.width=parseInt(options.width,10)}}if(!this.parent){this.width=options.width;this.height=options.height;this.margins=options.margins;this.paddings=options.paddings}if(this.compatVersion()<=1){options.plot2=this._allowV1SecondAxis&&!!options.secondAxis}this._processOptionsCore(options);this._processExtensionPoints();return options},_processOptionsCore:function(options){if(!this.parent){if(!$.support.svg||pv.renderer()==='batik'){options.animate=false}this._processTooltipOptions(options)}},_tooltipDefaults:{gravity:'s',delayIn:200,delayOut:80,offset:2,opacity:0.9,html:true,fade:true,useCorners:false,arrowVisible:true,followMouse:false,format:undefined},_processTooltipOptions:function(options){var isV1Compat=this.compatVersion()<=1;var tipOptions=options.tooltip;var tipEnabled=options.tooltipEnabled;if(tipEnabled==null){if(tipOptions){tipEnabled=tipOptions.enabled}if(tipEnabled==null){if(isV1Compat){tipEnabled=options.showTooltips}if(tipEnabled==null){tipEnabled=true}}}if(tipEnabled){if(!tipOptions){tipOptions={}}if(isV1Compat){this._importV1TooltipOptions(tipOptions,options)}def.eachOwn(this._tooltipDefaults,function(dv,p){var value=options['tooltip'+def.firstUpperCase(p)];if(value!==undefined){tipOptions[p]=value}else if(tipOptions[p]===undefined){tipOptions[p]=dv}})}else{tipOptions={}}this._tooltipEnabled=tipEnabled;this._tooltipOptions=tipOptions},_importV1TooltipOptions:function(tipOptions,options){var v1TipOptions=options.tipsySettings;if(v1TipOptions){this.extend(v1TipOptions,"tooltip");for(var p in v1TipOptions){if(tipOptions[p]===undefined){tipOptions[p]=v1TipOptions[p]}}if(tipOptions.html==null){tipOptions.html=false}}},render:function(bypassAnimation,recreate,reloadData){var hasError;if(pvc.debug>1){pvc.group("CCC RENDER")}this._suspendSelectionUpdate();try{this.useTextMeasureCache(function(){try{if(!this.isPreRendered||recreate){this._preRender({reloadData:reloadData})}else if(!this.parent&&this.isPreRendered){pvc.removeTipsyLegends()}this.basePanel.render({bypassAnimation:bypassAnimation,recreate:recreate})}catch(e){if(e instanceof NoDataException){if(pvc.debug>1){this._log("No data found.")}this._addErrorPanelMessage("No data found",true)}else{hasError=true;pvc.logError(e.message);if(pvc.debug>0){this._addErrorPanelMessage("Error: "+e.message,false)}}}})}finally{if(!hasError){this._resumeSelectionUpdate()}if(pvc.debug>1){pvc.groupEnd()}}return this},_addErrorPanelMessage:function(text,isNoData){var options=this.options,pvPanel=new pv.Panel().canvas(options.canvas).width(this.width).height(this.height),pvMsg=pvPanel.anchor("center").add(pv.Label).text(text);if(isNoData){this.extend(pvMsg,"noDataMessage")}pvPanel.render()},useTextMeasureCache:function(fun,ctx){var root=this.root;var textMeasureCache=root._textMeasureCache||(root._textMeasureCache=pv.Text.createCache());return pv.Text.usingCache(textMeasureCache,fun,ctx||this)},animate:function(start,end){return this.basePanel.animate(start,end)},isAnimatingStart:function(){return this.basePanel.isAnimatingStart()},isOrientationVertical:function(orientation){return(orientation||this.options.orientation)===pvc.orientation.vertical},isOrientationHorizontal:function(orientation){return(orientation||this.options.orientation)===pvc.orientation.horizontal},dispose:function(){if(!this._disposed){this._disposed=true}},defaults:{width:400,height:300,orientation:'vertical',ignoreNulls:true,crosstabMode:true,isMultiValued:false,seriesInRows:false,groupedLabelSep:undefined,animate:true,titlePosition:"top",titleAlign:"center",legend:false,legendPosition:"bottom",v1StyleTooltipFormat:function(s,c,v,datum){return s+", "+c+": "+this.chart.options.valueFormat(v)+(datum&&datum.percent?(" ("+datum.percent.label+")"):"")},valueFormat:def.scope(function(){var pvFormat=pv.Format.number().fractionDigits(0,2);return function(d){return pvFormat.format(d)}}),percentValueFormat:def.scope(function(){var pvFormat=pv.Format.number().fractionDigits(0,1);return function(d){return pvFormat.format(d*100)+"%"}}),clickable:false,doubleClickMaxDelay:300,hoverable:false,selectable:false,selectionMode:'rubberband',ctrlSelectMode:true,clearSelectionMode:'emptySpaceClick',compatVersion:Infinity}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBaseChart.panels.js b/pacotes/ccc2/compacto/pvcBaseChart.panels.js deleted file mode 100755 index 4c3a1b4..0000000 --- a/pacotes/ccc2/compacto/pvcBaseChart.panels.js +++ /dev/null @@ -1 +0,0 @@ -pvc.BaseChart.add({basePanel:null,titlePanel:null,legendPanel:null,_multiChartPanel:null,_initChartPanels:function(hasMultiRole){this._initBasePanel();this._initTitlePanel();var legendPanel=this._initLegendPanel();if(!this.parent&&hasMultiRole){this._initMultiChartPanel();if(legendPanel){this._initLegendScenes(legendPanel)}}else{var options=this.options;if(legendPanel){this._initLegendScenes(legendPanel)}this._preRenderContent({margins:hasMultiRole?options.smallContentMargins:options.contentMargins,paddings:hasMultiRole?options.smallContentPaddings:options.contentPaddings,clickAction:options.clickAction,doubleClickAction:options.doubleClickAction})}},_preRenderContent:function(contentOptions){},_initBasePanel:function(){var options=this.options;var basePanelParent=this.parent&&this.parent._multiChartPanel;this.basePanel=new pvc.BasePanel(this,basePanelParent,{margins:this.margins,paddings:this.paddings,size:{width:this.width,height:this.height}})},_initTitlePanel:function(){var options=this.options;if(!def.empty(options.title)){var isRoot=!this.parent;this.titlePanel=new pvc.TitlePanel(this,this.basePanel,{title:options.title,font:options.titleFont,anchor:options.titlePosition,align:options.titleAlign,alignTo:options.titleAlignTo,offset:options.titleOffset,keepInBounds:options.titleKeepInBounds,margins:options.titleMargins,paddings:options.titlePaddings,titleSize:options.titleSize,titleSizeMax:options.titleSizeMax})}},_initLegendPanel:function(){var options=this.options;if(options.legend){var legend=new pvc.visual.Legend(this,'legend',0);this.legendPanel=new pvc.LegendPanel(this,this.basePanel,{anchor:legend.option('Position'),align:legend.option('Align'),alignTo:options.legendAlignTo,offset:options.legendOffset,keepInBounds:options.legendKeepInBounds,size:legend.option('Size'),sizeMax:legend.option('SizeMax'),margins:legend.option('Margins'),paddings:legend.option('Paddings'),font:legend.option('Font'),scenes:def.getPath(options,'legend.scenes'),textMargin:options.legendTextMargin,itemPadding:options.legendItemPadding,markerSize:options.legendMarkerSize});return this.legendPanel}},_getLegendBulletRootScene:function(){return this.legendPanel&&this.legendPanel._getBulletRootScene()},_initMultiChartPanel:function(){var basePanel=this.basePanel;var options=this.options;this._multiChartPanel=new pvc.MultiChartPanel(this,basePanel,{margins:options.contentMargins,paddings:options.contentPaddings});this._multiChartPanel.createSmallCharts();basePanel._children.unshift(basePanel._children.pop())},_coordinateSmallChartsLayout:function(scopesByType){},_initLegendScenes:function(legendPanel){var rootScene,dataPartDimName;var legendIndex=0;var colorAxes=this.axesByType.color;if(colorAxes){colorAxes.forEach(processAxis,this)}function processAxis(colorAxis){if(colorAxis.option('LegendVisible')){var dataCells=colorAxis&&colorAxis.dataCells;if(dataCells){dataCells.forEach(function(dataCell){if(dataCell.role.isDiscrete()){var domainData=dataCell.data;if(!rootScene){dataPartDimName=this._getDataPartDimName();rootScene=legendPanel._getBulletRootScene()}var dataPartAtom;var locked=colorAxis.option('LegendClickMode')==='toggleVisible'&&(dataPartAtom=domainData.atoms[dataPartDimName])&&dataPartAtom.value==='trend';var groupScene=rootScene.createGroup({group:domainData,colorAxis:colorAxis,clickMode:locked?'none':undefined,extensionPrefix:pvc.buildIndexedId('',legendIndex++)});dataCell.legendBulletGroupScene=groupScene;var partColorScale=colorAxis.scale;domainData.children().each(function(itemData){var itemScene=groupScene.createItem({group:itemData});itemScene.color=partColorScale(itemData.value)})}},this)}}}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBaseChart.plots.js b/pacotes/ccc2/compacto/pvcBaseChart.plots.js deleted file mode 100755 index 6e816df..0000000 --- a/pacotes/ccc2/compacto/pvcBaseChart.plots.js +++ /dev/null @@ -1 +0,0 @@ -pvc.BaseChart.add({_initPlots:function(hasMultiRole){this.plotPanelList=null;if(!this.parent){this.plots={};this.plotList=[];this.plotsByType={};this._initPlotsCore(hasMultiRole)}else{var root=this.root;this.plots=root.plots;this.plotList=root.plotList;this.plotsByType=root.plotsByType}},_initPlotsCore:function(){},_addPlot:function(plot){var plotsByType=this.plotsByType;var plots=this.plots;var plotType=plot.type;var plotIndex=plot.index;var plotName=plot.name;var plotId=plot.id;if(plotName&&def.hasOwn(plots,plotName)){throw def.error.operationInvalid("Plot name '{0}' already taken.",[plotName])}if(def.hasOwn(plots,plotId)){throw def.error.operationInvalid("Plot id '{0}' already taken.",[plotId])}var typePlots=def.array.lazy(plotsByType,plotType);if(def.hasOwn(typePlots,plotIndex)){throw def.error.operationInvalid("Plot index '{0}' of type '{1}' already taken.",[plotIndex,plotType])}plot.globalIndex=this.plotList.length;typePlots[plotIndex]=plot;this.plotList.push(plot);plots[plotId]=plot;if(plotName){plots[plotName]=plot}},_collectPlotAxesDataCells:function(plot,dataCellsByAxisTypeThenIndex){var colorRoleName=plot.option('ColorRole');if(colorRoleName){var colorRole=this.visualRoles(colorRoleName);if(colorRole.isBound()){var colorDataCellsByAxisIndex=def.array.lazy(dataCellsByAxisTypeThenIndex,'color');def.array.lazy(colorDataCellsByAxisIndex,plot.option('ColorAxis')-1).push({plot:plot,role:colorRole,dataPartValue:plot.option('DataPart')})}}},_addPlotPanel:function(plotPanel){def.lazy(this,'plotPanels')[plotPanel.plot.id]=plotPanel;def.array.lazy(this,'plotPanelList').push(plotPanel)},_createPlotPanels:function(){throw def.error.notImplemented()}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBaseChart.selection.js b/pacotes/ccc2/compacto/pvcBaseChart.selection.js deleted file mode 100755 index 01aec62..0000000 --- a/pacotes/ccc2/compacto/pvcBaseChart.selection.js +++ /dev/null @@ -1 +0,0 @@ -pvc.BaseChart.add({_updateSelectionSuspendCount:0,_lastSelectedDatums:null,clearSelections:function(){if(this.data.owner.clearSelected()){this.updateSelections()}return this},_updatingSelections:function(method,context){this._suspendSelectionUpdate();try{method.call(context||this)}finally{this._resumeSelectionUpdate()}},_suspendSelectionUpdate:function(){if(this===this.root){this._updateSelectionSuspendCount++}else{this.root._suspendSelectionUpdate()}},_resumeSelectionUpdate:function(){if(this===this.root){if(this._updateSelectionSuspendCount>0){if(!(--this._updateSelectionSuspendCount)){this.updateSelections()}}}else{this.root._resumeSelectionUpdate()}},updateSelections:function(keyArgs){if(this===this.root){if(this._inUpdateSelections){return this}if(this._updateSelectionSuspendCount){return this}var selectedChangedDatumMap=this._calcSelectedChangedDatums();if(!selectedChangedDatumMap){return}pvc.removeTipsyLegends();this._inUpdateSelections=true;try{var action=this.options.selectionChangedAction;if(action){var selectedDatums=this.data.selectedDatums();var selectedChangedDatums=selectedChangedDatumMap.values();action.call(this.basePanel._getContext(),selectedDatums,selectedChangedDatums)}if(def.get(keyArgs,'render',true)){this.useTextMeasureCache(function(){this.basePanel.renderInteractive()},this)}}finally{this._inUpdateSelections=false}}else{this.root.updateSelections()}return this},_calcSelectedChangedDatums:function(){var selectedChangedDatums;var nowSelectedDatums=this.data.selectedDatumMap();var lastSelectedDatums=this._lastSelectedDatums;if(!lastSelectedDatums){if(!nowSelectedDatums.count){return}selectedChangedDatums=nowSelectedDatums.clone()}else{selectedChangedDatums=lastSelectedDatums.symmetricDifference(nowSelectedDatums);if(!selectedChangedDatums.count){return}}this._lastSelectedDatums=nowSelectedDatums;var datums=this._lastSelectedDatums?this._lastSelectedDatums.values():[];return selectedChangedDatums},_onUserSelection:function(datums){if(!datums||!datums.length){return datums}if(this===this.root){var action=this.options.userSelectionAction;if(action){return action.call(null,datums)||datums}return datums}return this.root._onUserSelection(datums)},_isSelectable:function(){return this.options.selectable},_canSelectWithRubberband:function(){var options=this.options;return options.selectable&&options.selectionMode==='rubberband'},_canSelectWithClick:function(){return this._canSelectWithRubberband()},_canSelectWithFocusWindow:function(){var options=this.options;return options.selectable&&options.selectionMode==='focuswindow'}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBaseChart.visualRoles.js b/pacotes/ccc2/compacto/pvcBaseChart.visualRoles.js deleted file mode 100755 index bdc99d5..0000000 --- a/pacotes/ccc2/compacto/pvcBaseChart.visualRoles.js +++ /dev/null @@ -1 +0,0 @@ -pvc.BaseChart.add({_visualRoles:null,_visualRoleList:null,_serRole:null,_dataPartRole:null,_measureVisualRoles:null,_constructVisualRoles:function(){var parent=this.parent;if(parent){this._visualRoles=parent._visualRoles;this._visualRoleList=parent._visualRoleList;this._measureVisualRoles=parent._measureVisualRoles;if(parent._multiChartRole){this._multiChartRole=parent._multiChartRole}if(parent._serRole){this._serRole=parent._serRole}if(parent._colorRole){this._colorRole=parent._colorRole}if(parent._dataPartRole){this._dataPartRole=parent._dataPartRole}}else{this._visualRoles={};this._visualRoleList=[];this._measureVisualRoles=[]}},_hasDataPartRole:function(){return false},_getSeriesRoleSpec:function(){return null},_getColorRoleSpec:function(){return null},_addVisualRole:function(name,keyArgs){keyArgs=def.set(keyArgs,'index',this._visualRoleList.length);var visualRole=new pvc.visual.Role(name,keyArgs);this._visualRoleList.push(visualRole);this._visualRoles[name]=visualRole;if(visualRole.isMeasure){this._measureVisualRoles.push(visualRole)}return visualRole},_initVisualRoles:function(){this._multiChartRole=this._addVisualRole('multiChart',{defaultDimension:'multiChart*',requireIsDiscrete:true});if(this._hasDataPartRole()){this._dataPartRole=this._addVisualRole('dataPart',{defaultDimension:'dataPart',requireSingleDimension:true,requireIsDiscrete:true,dimensionDefaults:{isHidden:true,comparer:def.compare}})}var serRoleSpec=this._getSeriesRoleSpec();if(serRoleSpec){this._serRole=this._addVisualRole('series',serRoleSpec)}var colorRoleSpec=this._getColorRoleSpec();if(colorRoleSpec){this._colorRole=this._addVisualRole('color',colorRoleSpec)}},_bindVisualRolesPreI:function(){def.eachOwn(this._visualRoles,function(role){role.setIsReversed(false)});var sourcedRoles=[];var options=this.options;var roleOptions=options.visualRoles;this._visualRoleList.forEach(function(visualRole){var name=visualRole.name;var roleSpec=options[name+'Role'];if(roleSpec!==undefined){if(!roleOptions){roleOptions=options.visualRoles={}}if(roleOptions[name]===undefined){roleOptions[name]=roleSpec}}});var dimsBoundToSingleRole;if(roleOptions){dimsBoundToSingleRole={};var rolesWithOptions=def.query(def.keys(roleOptions)).select(function(name){return this._visualRoles[name]||def.fail.operationInvalid("Role '{0}' is not supported by the chart type.",[name])},this).array();rolesWithOptions.sort(function(a,b){return a.index-b.index});rolesWithOptions.forEach(function(visualRole){var name=visualRole.name;var roleSpec=roleOptions[name];var groupingSpec,sourceRoleName;if(def.object.is(roleSpec)){if(def.nullyTo(roleSpec.isReversed,false)){visualRole.setIsReversed(true)}sourceRoleName=roleSpec.from;if(sourceRoleName&&(sourceRoleName!==name)){var sourceRole=this._visualRoles[sourceRoleName]||def.fail.operationInvalid("Source role '{0}' is not supported by the chart type.",[sourceRoleName]);visualRole.setSourceRole(sourceRole);sourcedRoles.push(visualRole)}else{groupingSpec=roleSpec.dimensions}}else{groupingSpec=roleSpec}if(groupingSpec!==undefined){var grouping=pvc.data.GroupingSpec.parse(groupingSpec);visualRole.preBind(grouping);grouping.dimensions().each(function(groupDimSpec){if(def.hasOwn(dimsBoundToSingleRole,groupDimSpec.name)){delete dimsBoundToSingleRole[groupDimSpec.name]}else{dimsBoundToSingleRole[groupDimSpec.name]=visualRole}})}},this)}this._sourcedRoles=sourcedRoles;this._dimsBoundToSingleRole=dimsBoundToSingleRole},_bindVisualRolesPreII:function(){var dimsBoundToSingleRole=this._dimsBoundToSingleRole;if(dimsBoundToSingleRole){delete this._dimsBoundToSingleRole;def.eachOwn(dimsBoundToSingleRole,this._setRoleBoundDimensionDefaults,this)}var sourcedRoles=this._sourcedRoles;delete this._sourcedRoles;def.query(this._visualRoleList).where(function(role){return role.defaultSourceRoleName&&!role.sourceRole&&!role.isPreBound()}).each(function(role){var sourceRole=this._visualRoles[role.defaultSourceRoleName];if(sourceRole){role.setSourceRole(sourceRole);sourcedRoles.push(role)}},this);sourcedRoles.forEach(function(role){var sourceRole=role.sourceRole;if(sourceRole.isReversed){role.setIsReversed(!role.isReversed)}if(!role.defaultDimensionName&&sourceRole.isPreBound()){role.preBind(sourceRole.preBoundGrouping())}})},_setRoleBoundDimensionDefaults:function(role,dimName){this._complexTypeProj.setDimDefaults(dimName,role.dimensionDefaults)},_bindVisualRolesPostI:function(){var complexTypeProj=this._complexTypeProj;var boundDimTypes={};var unboundSourcedRoles=[];def.query(this._visualRoleList).where(function(role){return role.isPreBound()}).each(markPreBoundRoleDims,this);def.query(this._visualRoleList).where(function(role){return!role.isPreBound()}).each(autoBindUnboundRole,this);unboundSourcedRoles.forEach(tryPreBindSourcedRole,this);def.query(def.ownKeys(boundDimTypes)).where(function(dimName){return boundDimTypes[dimName].length===1}).each(function(dimName){var singleRole=boundDimTypes[dimName][0];this._setRoleBoundDimensionDefaults(singleRole,dimName)},this);function markDimBoundTo(dimName,role){def.array.lazy(boundDimTypes,dimName).push(role)}function dimIsDefined(dimName){return complexTypeProj.hasDim(dimName)}function preBindRoleTo(role,dimNames){if(def.array.is(dimNames)){dimNames.forEach(function(dimName){markDimBoundTo(dimName,role)})}else{markDimBoundTo(dimNames,role)}role.setSourceRole(null);role.preBind(pvc.data.GroupingSpec.parse(dimNames))}function preBindRoleToGroupDims(role,groupDimNames){if(groupDimNames.length){if(role.requireSingleDimension){preBindRoleTo(role,groupDimNames[0])}else{preBindRoleTo(role,groupDimNames)}}}function preBindRoleToNewDim(role,dimName){complexTypeProj.setDim(dimName,{isHidden:true});preBindRoleTo(role,dimName)}function roleIsUnbound(role){if(role.isRequired){throw def.error.operationInvalid("Chart type requires unassigned role '{0}'.",[role.name])}role.bind(null);role.setSourceRole(null)}function markPreBoundRoleDims(role){role.preBoundGrouping().dimensionNames().forEach(markDimBoundTo)}function autoBindUnboundRole(role){var name=role.name;var dimName=role.defaultDimensionName;if(!dimName){if(role.sourceRole){unboundSourcedRoles.push(role)}else{roleIsUnbound(role)}return}var match=dimName.match(/^(.*?)(\*)?$/)||def.fail.argumentInvalid('defaultDimensionName');var defaultName=match[1];var greedy=match[2];if(greedy){var groupDimNames=complexTypeProj.groupDimensionsNames(defaultName);if(groupDimNames){preBindRoleToGroupDims(role,groupDimNames);return}}else if(dimIsDefined(defaultName)){preBindRoleTo(role,defaultName);return}if(role.autoCreateDimension){preBindRoleToNewDim(role,defaultName);return}if(role.sourceRole){unboundSourcedRoles.push(role)}else{roleIsUnbound(role)}}function tryPreBindSourcedRole(role){var sourceRole=role.sourceRole;if(sourceRole.isPreBound()){role.preBind(sourceRole.preBoundGrouping())}else{roleIsUnbound(role)}}},_bindVisualRolesPostII:function(complexType){def.query(this._visualRoleList).where(function(role){return role.isPreBound()}).each(commitRolePreBinding,this);function commitRolePreBinding(role){role.postBind(complexType)}},_logVisualRoles:function(){var out=["VISUAL ROLES MAP SUMMARY",pvc.logSeparator," VisualRole <-- Dimensions",pvc.logSeparator];def.eachOwn(this._visualRoles,function(role,name){out.push(" "+name+def.array.create(18-name.length," ").join("")+(role.grouping?(" <-- "+role.grouping):''))});this._log(out.join("\n"))},visualRoles:function(roleName,keyArgs){if(roleName==null){return def.own(this._visualRoles)}var role=def.getOwn(this._visualRoles,roleName)||null;if(!role&&def.get(keyArgs,'assertExists',true)){throw def.error.argumentInvalid('roleName',"Undefined role name '{0}'.",[roleName])}return role},measureVisualRoles:function(){return this._measureVisualRoles},measureDimensionsNames:function(){return def.query(this._measureVisualRoles).select(function(visualRole){return visualRole.firstDimensionName()}).where(def.notNully).array()},_isRoleAssigned:function(roleName){return!!this._visualRoles[roleName].grouping},_getDataPartDimName:function(){var role=this._dataPartRole;if(role){if(role.isBound()){return role.firstDimensionName()}var preGrouping=role.preBoundGrouping();if(preGrouping){return preGrouping.firstDimensionName()}return role.defaultDimensionName}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBasePanel.js b/pacotes/ccc2/compacto/pvcBasePanel.js deleted file mode 100755 index c4516b0..0000000 --- a/pacotes/ccc2/compacto/pvcBasePanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.BasePanel',pvc.Abstract).init(function(chart,parent,options){this.chart=chart;this.base();this.axes={};if(options){if(options.scenes){this._sceneTypeExtensions=options.scenes;delete options.scenes}var axes=options.axes;if(axes){def.copy(this.axes,axes);delete options.axes}}$.extend(this,options);this.chart=chart;if(!this.axes.color){this.axes.color=chart.axes.color}this.position={};var margins=options&&options.margins;if(!parent&&margins===undefined){margins=3}this.margins=new pvc.Sides(margins);this.paddings=new pvc.Sides(options&&options.paddings);this.size=new pvc.Size(options&&options.size);this.sizeMax=new pvc.Size(options&&options.sizeMax);if(!parent){this.parent=null;this.root=this;this.topRoot=this;this.isRoot=true;this.isTopRoot=true;this.data=this.chart.data}else{this.parent=parent;this.isTopRoot=false;this.isRoot=(parent.chart!==chart);this.root=this.isRoot?this:parent.root;this.topRoot=parent.topRoot;this.data=parent.data;if(this.isRoot){this.position.left=chart.left;this.position.top=chart.top}parent._addChild(this)}if(this.isRoot){this.anchor=null;this.align=null;this.alignTo=null;this.offset=null}else{this.align=pvc.parseAlign(this.anchor,this.align);var alignTo=this.alignTo;var side=this.anchor;if(alignTo!=null&&alignTo!==''&&(side==='left'||side==='right')){if(alignTo!=='page-middle'){if(!isNaN(+alignTo.charAt(0))){alignTo=pvc.PercentValue.parse(alignTo)}else{alignTo=pvc.parseAlign(side,alignTo)}}}else{alignTo=this.align}this.alignTo=alignTo;this.offset=new pvc.Offset(this.offset)}if(this.borderWidth==null){var borderWidth;var extensionId=this._getExtensionId();if(extensionId){var strokeStyle=this._getExtension(extensionId,'strokeStyle');if(strokeStyle!=null){borderWidth=+this._getConstantExtension(extensionId,'lineWidth');if(isNaN(borderWidth)||!isFinite(borderWidth)){borderWidth=null}}}this.borderWidth=borderWidth==null?0:1.5}}).add({chart:null,parent:null,_children:null,type:pv.Panel,_extensionPrefix:'',height:null,width:null,borderWidth:null,anchor:"top",pvPanel:null,margins:null,paddings:null,isRoot:false,isTopRoot:false,root:null,topRoot:null,_layoutInfo:null,_signs:null,data:null,dataPartValue:null,_isAnimating:0,_isRubberBandSelecting:false,_ignoreClicks:0,_v1DimRoleName:{'series':'series','category':'category','value':'value'},_sceneTypeExtensions:null,clickAction:null,doubleClickAction:null,compatVersion:function(options){return this.chart.compatVersion(options)},_createLogInstanceId:function(){return""+this.constructor+this.chart._createLogChildSuffix()},defaultVisibleBulletGroupScene:function(){var colorAxis=this.axes.color;if(colorAxis&&colorAxis.option('LegendVisible')){var dataPartValue=this.dataPartValue;return def.query(colorAxis.dataCells).where(function(dataCell){return dataCell.dataPartValue===dataPartValue}).select(function(dataCell){return dataCell.legendBulletGroupScene}).first(def.truthy)}return null},_getLegendBulletRootScene:function(){return this.chart._getLegendBulletRootScene()},_addChild:function(child){child.parent===this||def.assert("Child has a != parent.");(this._children||(this._children=[])).push(child)},_addSign:function(sign){(this._signs||(this._signs=[])).push(sign)},visibleData:function(){return this.chart.visibleData(this.dataPartValue)},layout:function(availableSize,keyArgs){if(!this._layoutInfo||def.get(keyArgs,'force',false)){var referenceSize=def.get(keyArgs,'referenceSize');if(!referenceSize&&availableSize){referenceSize=def.copyOwn(availableSize)}var desiredSize=this.size.resolve(referenceSize);var sizeMax=this.sizeMax.resolve(referenceSize);if(!availableSize){if(desiredSize.width==null||desiredSize.height==null){throw def.error.operationInvalid("Panel layout without width or height set.")}availableSize=def.copyOwn(desiredSize)}if(!referenceSize&&availableSize){referenceSize=def.copyOwn(availableSize)}if(sizeMax.width!=null&&availableSize.width>sizeMax.width){availableSize.width=sizeMax.width}if(sizeMax.height!=null&&availableSize.height>sizeMax.height){availableSize.height=sizeMax.height}var halfBorder=this.borderWidth/2;var realMargins=(def.get(keyArgs,'margins')||this.margins).resolve(referenceSize);var realPaddings=(def.get(keyArgs,'paddings')||this.paddings).resolve(referenceSize);var margins=pvc.Sides.inflate(realMargins,halfBorder);var paddings=pvc.Sides.inflate(realPaddings,halfBorder);var spaceWidth=margins.width+paddings.width;var spaceHeight=margins.height+paddings.height;var availableClientSize=new pvc.Size(Math.max(availableSize.width-spaceWidth,0),Math.max(availableSize.height-spaceHeight,0));var desiredClientSize=def.copyOwn(desiredSize);if(desiredClientSize.width!=null){desiredClientSize.width=Math.max(desiredClientSize.width-spaceWidth,0)}if(desiredClientSize.height!=null){desiredClientSize.height=Math.max(desiredClientSize.height-spaceHeight,0)}var prevLayoutInfo=this._layoutInfo||null;var canChange=def.get(keyArgs,'canChange',true);var layoutInfo=this._layoutInfo={canChange:canChange,referenceSize:referenceSize,realMargins:realMargins,realPaddings:realPaddings,borderWidth:this.borderWidth,margins:margins,paddings:paddings,desiredClientSize:desiredClientSize,clientSize:availableClientSize,pageClientSize:prevLayoutInfo?prevLayoutInfo.pageClientSize:availableClientSize.clone(),previous:prevLayoutInfo};if(prevLayoutInfo){delete prevLayoutInfo.previous;delete prevLayoutInfo.pageClientSize}var clientSize=this._calcLayout(layoutInfo);var size;if(!clientSize){size=availableSize;clientSize=availableClientSize}else{layoutInfo.clientSize=clientSize;size={width:clientSize.width+spaceWidth,height:clientSize.height+spaceHeight}}this.isVisible=(clientSize.width>0&&clientSize.height>0);delete layoutInfo.desiredClientSize;this.width=size.width;this.height=size.height;if(!canChange&&prevLayoutInfo){delete layoutInfo.previous}if(pvc.debug>=5){this._log("Size = "+pvc.stringify(size));this._log("Margins = "+pvc.stringify(layoutInfo.margins));this._log("Paddings = "+pvc.stringify(layoutInfo.paddings));this._log("ClientSize = "+pvc.stringify(layoutInfo.clientSize))}this._onLaidOut()}},_onLaidOut:function(){if(this.isRoot){this.chart._onLaidOut()}},_calcLayout:function(layoutInfo){var clientSize;var me=this;var margins,remSize,useLog;if(me._children){var aolMap=pvc.BasePanel.orthogonalLength;var aoMap=pvc.BasePanel.relativeAnchor;var altMap=pvc.BasePanel.leftTopAnchor;var aofMap=pvc.Offset.namesSidesToOffset;var fillChildren=[];var sideChildren=[];me._children.forEach(function(child){var a=child.anchor;if(a){if(a==='fill'){fillChildren.push(child)}else{def.hasOwn(aoMap,a)||def.fail.operationInvalid("Unknown anchor value '{0}'",[a]);sideChildren.push(child)}}});useLog=pvc.debug>=5;clientSize=def.copyOwn(layoutInfo.clientSize);var childKeyArgs={force:true,referenceSize:clientSize};if(useLog){me._group("CCC DOCK LAYOUT clientSize = "+pvc.stringify(clientSize))}try{doMaxTimes(5,layoutCycle,me)}finally{if(useLog){me._groupEnd()}}}return clientSize;function doMaxTimes(maxTimes,fun,ctx){var index=0;while(maxTimes--){if(fun.call(ctx,maxTimes,index)===false){return true}index++}return false}function layoutCycle(remTimes,iteration){if(useLog){me._group("LayoutCycle #"+(iteration+1)+" (remaining: "+remTimes+")")}try{var canResize=(remTimes>0);margins=new pvc.Sides(0);remSize=def.copyOwn(clientSize);var child;var index=0;var count=sideChildren.length;while(index0;child.layout(new pvc.Size(remSize),childKeyArgs);if(child.isVisible){resized=checkChildResize.call(this,child,canResize);if(resized){return false}var requestPaddings=child._layoutInfo.requestPaddings;if(checkPaddingsChanged(paddings,requestPaddings)){paddings=requestPaddings;if(remTimes>0){paddings=new pvc.Sides(paddings);if(useLog){this._log("Child requested paddings change: "+pvc.stringify(paddings))}return true}if(pvc.debug>=2){this._warn("Child requests paddings change but iterations limit has been reached.")}}positionChild.call(this,child);if(child.anchor!=='fill'){updateSide.call(this,child)}}return false}finally{if(useLog){me._groupEnd()}}},this);return resized}function checkPaddingsChanged(paddings,newPaddings){if(!newPaddings){return false}return def.query(pvc.Sides.names).each(function(side){var curPad=(paddings&&paddings[side])||0;var newPad=(newPaddings&&newPaddings[side])||0;if(Math.abs(newPad-curPad)>=0.1){return false}})}function checkChildResize(child,canResize){var resized=false;var addWidth=child.width-remSize.width;if(addWidth>0){if(pvc.debug>=3){this._log("Child added width = "+addWidth)}if(!canResize){if(pvc.debug>=2){this._warn("Child wanted more width, but layout iterations limit has been reached.")}}else{resized=true;remSize.width+=addWidth;clientSize.width+=addWidth}}var addHeight=child.height-remSize.height;if(addHeight>0){if(pvc.debug>=3){this._log("Child added height ="+addHeight)}if(!canResize){if(pvc.debug>=2){this._warn("Child wanted more height, but layout iterations limit has been reached.")}}else{resized=true;remSize.height+=addHeight;clientSize.height+=addHeight}}return resized}function positionChild(child){var side=child.anchor;var align=child.align;var alignTo=child.alignTo;var sidePos;if(side==='fill'){side='left';sidePos=margins.left+remSize.width/2-(child.width/2);align=alignTo='middle'}else{sidePos=margins[side]}var sideo,sideOPosChildOffset;switch(align){case'top':case'bottom':case'left':case'right':sideo=align;sideOPosChildOffset=0;break;case'center':case'middle':sideo=altMap[aoMap[side]];sideOPosChildOffset=-child[aolMap[sideo]]/2;break}var sideOPosParentOffset;var sideOTo;switch(alignTo){case'top':case'bottom':case'left':case'right':sideOTo=alignTo;sideOPosParentOffset=(sideOTo!==sideo)?remSize[aolMap[sideo]]:0;break;case'center':case'middle':sideOTo=altMap[aoMap[side]];sideOPosParentOffset=remSize[aolMap[sideo]]/2;break;case'page-center':case'page-middle':sideOTo=altMap[aoMap[side]];var lenProp=aolMap[sideo];var pageLen=Math.min(remSize[lenProp],layoutInfo.pageClientSize[lenProp]);sideOPosParentOffset=pageLen/2;break}var sideOPos=margins[sideOTo]+sideOPosParentOffset+sideOPosChildOffset;var resolvedOffset=child.offset.resolve(remSize);if(resolvedOffset){sidePos+=resolvedOffset[aofMap[side]]||0;sideOPos+=resolvedOffset[aofMap[sideo]]||0}if(child.keepInBounds){if(sidePos<0){sidePos=0}if(sideOPos<0){sideOPos=0}}child.setPosition(def.set({},side,sidePos,sideo,sideOPos))}function updateSide(child){var side=child.anchor;var sideol=aolMap[side];var olen=child[sideol];margins[side]+=olen;remSize[sideol]-=olen}},invalidateLayout:function(){this._layoutInfo=null;if(this._children){this._children.forEach(function(child){child.invalidateLayout()})}},_create:function(force){if(!this.pvPanel||force){this.pvPanel=null;delete this._signs;this.layout();if(!this.isVisible){return}if(this.isRoot){this._creating()}var margins=this._layoutInfo.margins;var paddings=this._layoutInfo.paddings;if(this.isTopRoot){this.pvRootPanel=this.pvPanel=new pv.Panel().canvas(this.chart.options.canvas);if(margins.width>0||margins.height>0){this.pvPanel.width(this.width).height(this.height);this.pvPanel=this.pvPanel.add(pv.Panel)}}else{this.pvPanel=this.parent.pvPanel.add(this.type)}var pvBorderPanel=this.pvPanel;var width=this.width-margins.width;var height=this.height-margins.height;pvBorderPanel.width(width).height(height);if(pvc.debug>=15&&(margins.width>0||margins.height>0)){(this.isTopRoot?this.pvRootPanel:this.parent.pvPanel).add(this.type).width(this.width).height(this.height).left(this.position.left!=null?this.position.left:null).right(this.position.right!=null?this.position.right:null).top(this.position.top!=null?this.position.top:null).bottom(this.position.bottom!=null?this.position.bottom:null).strokeStyle('orange').lineWidth(1).strokeDasharray('- .')}var hasPositions={};def.eachOwn(this.position,function(v,side){pvBorderPanel[side](v+margins[side]);hasPositions[this.anchorLength(side)]=true},this);if(!hasPositions.width){if(margins.left>0){pvBorderPanel.left(margins.left)}if(margins.right>0){pvBorderPanel.right(margins.right)}}if(!hasPositions.height){if(margins.top>0){pvBorderPanel.top(margins.top)}if(margins.bottom>0){pvBorderPanel.bottom(margins.bottom)}}if(paddings.width>0||paddings.height>0){this.pvPanel=pvBorderPanel.add(pv.Panel).width(width-paddings.width).height(height-paddings.height).left(paddings.left).top(paddings.top)}pvBorderPanel.borderPanel=pvBorderPanel;pvBorderPanel.paddingPanel=this.pvPanel;this.pvPanel.paddingPanel=this.pvPanel;this.pvPanel.borderPanel=pvBorderPanel;if(pvc.debug>=15){this.pvPanel.strokeStyle('lightgreen').lineWidth(1).strokeDasharray('- ');if(this.pvPanel!==pvBorderPanel){pvBorderPanel.strokeStyle('blue').lineWidth(1).strokeDasharray('. ')}}var extensionId=this._getExtensionId();new pvc.visual.Panel(this,null,{panel:pvBorderPanel,extensionId:extensionId});this._createCore(this._layoutInfo);if(this.isTopRoot&&pv.renderer()!=='batik'&&this.chart._canSelectWithRubberband()){this._initRubberBand()}this.applyExtensions()}},_creating:function(){if(this._children){this._children.forEach(function(child){child._creating()})}},_createCore:function(){if(this._children){this._children.forEach(function(child){child._create()})}},render:function(keyArgs){if(!this.isTopRoot){return this.topRoot.render(keyArgs)}this._create(def.get(keyArgs,'recreate',false));if(!this.isVisible){return}this._onRender();var options=this.chart.options;var pvPanel=this.pvRootPanel;var animate=this.chart._animatable&&options.animate;this._isAnimating=animate&&!def.get(keyArgs,'bypassAnimation',false)?1:0;try{pvPanel.render();if(this._isAnimating){this._isAnimating=2;var me=this;pvPanel.transition().duration(2000).ease("cubic-in-out").start(function(){me._isAnimating=0;me._onRenderEnd(true)})}else{this._onRenderEnd(false)}}finally{this._isAnimating=0}},_onRender:function(){var renderCallback=this.chart.options.renderCallback;if(renderCallback){if(this.compatVersion()<=1){renderCallback.call(this.chart)}else{var context=this._getContext();renderCallback.call(context,context.scene)}}},_onRenderEnd:function(animated){if(this._children){this._children.forEach(function(child){child._onRenderEnd(animated)})}},renderInteractive:function(){if(this.isVisible){var pvMarks=this._getSelectableMarks();if(pvMarks&&pvMarks.length){pvMarks.forEach(function(pvMark){pvMark.render()})}else if(!this._children){this.pvPanel.render();return}if(this._children){this._children.forEach(function(child){child.renderInteractive()})}}},_getSelectableMarks:function(){return null},animate:function(start,end){return(this.topRoot._isAnimating===1)?start:end},isAnimatingStart:function(){return(this.topRoot._isAnimating===1)},isAnimating:function(){return(this.topRoot._isAnimating>0)},setPosition:function(position){for(var side in position){if(def.hasOwn(pvc.Sides.namesSet,side)){var s=position[side];if(s===null){delete this.position[side]}else{s=+s;if(!isNaN(s)&&isFinite(s)){this.position[side]=s}}}}},createAnchoredSize:function(anchorLength,size){if(this.isAnchorTopOrBottom()){return new pvc.Size(size.width,Math.min(size.height,anchorLength))}return new pvc.Size(Math.min(size.width,anchorLength),size.height)},applyExtensions:function(){if(this._signs){this._signs.forEach(function(sign){sign.applyExtensions()})}},extend:function(mark,id,keyArgs){this.chart.extend(mark,this._makeExtensionAbsId(id),keyArgs)},extendAbs:function(mark,absId,keyArgs){this.chart.extend(mark,absId,keyArgs)},_extendSceneType:function(typeKey,type,names){var typeExts=def.get(this._sceneTypeExtensions,typeKey);if(typeExts){pvc.extendType(type,typeExts,names)}},_absBaseExtId:{abs:'base'},_absSmallBaseExtId:{abs:'smallBase'},_getExtensionId:function(){if(this.isRoot){return!this.chart.parent?this._absBaseExtId:this._absSmallBaseExtId}},_getExtensionPrefix:function(){return this._extensionPrefix},_makeExtensionAbsId:function(id){return pvc.makeExtensionAbsId(id,this._getExtensionPrefix())},_getExtension:function(id,prop){return this.chart._getExtension(this._makeExtensionAbsId(id),prop)},_getExtensionAbs:function(absId,prop){return this.chart._getExtension(absId,prop)},_getConstantExtension:function(id,prop){return this.chart._getConstantExtension(this._makeExtensionAbsId(id),prop)},getPvPanel:function(layer){var mainPvPanel=this.pvPanel;if(!layer){return mainPvPanel}if(!this.parent){throw def.error.operationInvalid("Layers are not possible in a root panel.")}if(!mainPvPanel){throw def.error.operationInvalid("Cannot access layer panels without having created the main panel.")}var pvPanel=null;if(!this._layers){this._layers={}}else{pvPanel=this._layers[layer]}if(!pvPanel){var pvParentPanel=this.parent.pvPanel;pvPanel=pvParentPanel.borderPanel.add(this.type).extend(mainPvPanel.borderPanel);var pvBorderPanel=pvPanel;if(mainPvPanel!==mainPvPanel.borderPanel){pvPanel=pvBorderPanel.add(pv.Panel).extend(mainPvPanel)}pvBorderPanel.borderPanel=pvBorderPanel;pvBorderPanel.paddingPanel=pvPanel;pvPanel.paddingPanel=pvPanel;pvPanel.borderPanel=pvBorderPanel;this.initLayerPanel(pvPanel,layer);this._layers[layer]=pvPanel}return pvPanel},initLayerPanel:function(){},_getV1DimName:function(v1Dim){var dimNames=this._v1DimName||(this._v1DimNameCache={});var dimName=dimNames[v1Dim];if(dimName==null){var role=this.chart.visualRoles(this._v1DimRoleName[v1Dim],{assertExists:false});dimName=role?role.firstDimensionName():'';dimNames[v1Dim]=dimName}return dimName},_getV1Datum:function(scene){return scene.datum},_createContext:function(mark,ev){return new pvc.visual.Context(this,mark,ev)},_getContext:function(mark,ev){var context=this._context;if(!context||context.isPinned){this._context=this._createContext(mark,ev)}else{visualContext_update.call(context,mark,ev)}return this._context},_isTooltipEnabled:function(){return!this.isRubberBandSelecting()&&!this.isAnimating()},_ensurePropEvents:function(pvMark){var events=pvMark.propertyValue('events',true);if(!events||events==='none'){pvMark.events('all')}},_addPropHoverable:function(pvMark){var panel=this;var onEvent;var offEvent;onEvent='mouseover';offEvent='mouseout';pvMark.event(onEvent,function(scene){if(!panel.isRubberBandSelecting()&&!panel.isAnimating()){scene.setActive(true);panel.renderInteractive()}}).event(offEvent,function(scene){if(!panel.isRubberBandSelecting()&&!panel.isAnimating()){if(scene.clearActive()){panel.renderInteractive()}}});this._ensurePropEvents(pvMark)},_addPropTooltip:function(pvMark,keyArgs){var chartTipOptions=this.chart._tooltipOptions;var tipOptions;var nowTipOptions=def.get(keyArgs,'options');if(nowTipOptions){tipOptions=def.create(chartTipOptions,nowTipOptions)}else{tipOptions=Object.create(chartTipOptions)}var buildTooltip=def.get(keyArgs,'buildTooltip')||this._getTooltipBuilder(tipOptions);if(!buildTooltip){return}tipOptions.isEnabled=this._isTooltipEnabled.bind(this);var tipsyEvent=def.get(keyArgs,'tipsyEvent');if(!tipsyEvent){tipsyEvent='mouseover'}var isLazy=def.get(keyArgs,'isLazy',true);pvMark.localProperty("tooltip").tooltip(this._createTooltipProp(pvMark,buildTooltip,isLazy)).title(function(){return''}).event(tipsyEvent,pv.Behavior.tipsy(tipOptions));this._ensurePropEvents(pvMark)},_getTooltipBuilder:function(tipOptions){var options=this.chart.options;var isV1Compat=this.compatVersion()<=1;var tooltipFormat=tipOptions.format;if(!tooltipFormat){if(!isV1Compat){return this._buildDataTooltip}tooltipFormat=options.v1StyleTooltipFormat;if(!tooltipFormat){return}}if(isV1Compat){return function(context){return tooltipFormat.call(context.panel,context.getV1Series(),context.getV1Category(),context.getV1Value()||'',context.getV1Datum())}}return function(context){return tooltipFormat.call(context,context.scene)}},_createTooltipProp:function(pvMark,buildTooltip,isLazy){var myself=this;if(!isLazy){return function(){var context=myself._getContext(pvMark,null);if(context.scene.isIntermediate){return null}return buildTooltip.call(myself,context)}}return function(){var context=myself._getContext(pvMark,null);if(context.scene.isIntermediate){return null}context.pin();var tooltip;return function(){if(tooltip==null){tooltip=buildTooltip.call(myself,context);context=null}return tooltip}}},_requirePointEvent:function(radius){if(!this.isTopRoot){return this.topRoot._requirePointEvent(radius)}if(!this._attachedPointEvent){this.pvPanel.events('all').event("mousemove",pv.Behavior.point(radius||20));this._attachedPointEvent=true}},_buildDataTooltip:function(context){var scene=context.scene;if(!scene.datum){return""}var group=scene.group;var isMultiDatumGroup=group&&group.count()>1;var firstDatum=scene.datum;if(!isMultiDatumGroup&&(!firstDatum||firstDatum.isNull)){return""}var data=this.data;var visibleKeyArgs={visible:true};var tooltip=[];if(firstDatum.isInterpolated){tooltip.push('Interpolation: '+def.html.escape(firstDatum.interpolation)+'
')}else if(firstDatum.isTrend){tooltip.push('Trend: '+def.html.escape(firstDatum.trendType)+'
')}var complexType=data.type;var playingPercentMap=context.panel.stacked===false?null:complexType.getPlayingPercentVisualRoleDimensionMap();var percentValueFormat=playingPercentMap?this.chart.options.percentValueFormat:null;var commonAtoms=isMultiDatumGroup?group.atoms:scene.datum.atoms;var commonAtomsKeys=complexType.sortDimensionNames(def.keys(commonAtoms));function addDim(escapedDimLabel,label){tooltip.push(''+escapedDimLabel+": "+(def.html.escape(label)||" - ")+'
')}function calcPercent(atom,dimName){var pct;if(group){pct=group.dimensions(dimName).percentOverParent(visibleKeyArgs)}else{pct=data.dimensions(dimName).percent(atom.value)}return percentValueFormat(pct)}var anyCommonAtom=false;commonAtomsKeys.forEach(function(dimName){var atom=commonAtoms[dimName];var dimType=atom.dimension.type;if(!dimType.isHidden){if(!isMultiDatumGroup||atom.value!=null){anyCommonAtom=true;var valueLabel=atom.label;if(playingPercentMap&&playingPercentMap.has(dimName)){valueLabel+=" ("+calcPercent(atom,dimName)+")"}addDim(def.html.escape(atom.dimension.type.label),valueLabel)}}},this);if(isMultiDatumGroup){if(anyCommonAtom){tooltip.push('
')}tooltip.push("#: "+group._datums.length+'
');complexType.sortDimensionNames(group.freeDimensionNames()).forEach(function(dimName){var dim=group.dimensions(dimName);if(!dim.type.isHidden){var dimLabel=def.html.escape(dim.type.label),valueLabel;if(dim.type.valueType===Number){valueLabel=dim.format(dim.sum(visibleKeyArgs));if(playingPercentMap&&playingPercentMap.has(dimName)){valueLabel+=" ("+calcPercent(null,dimName)+")"}dimLabel="∑ "+dimLabel}else{valueLabel=dim.atoms(visibleKeyArgs).map(function(atom){return atom.label||"- "}).join(", ")}addDim(dimLabel,valueLabel)}})}return'
'+tooltip.join('\n')+'
'},_addPropClick:function(pvMark){var myself=this;function onClick(){var ev=arguments[arguments.length-1];return myself._handleClick(this,ev)}pvMark.cursor("pointer").event("click",onClick);this._ensurePropEvents(pvMark)},_addPropDoubleClick:function(pvMark){var myself=this;function onDoubleClick(){var ev=arguments[arguments.length-1];return myself._handleDoubleClick(this,ev)}pvMark.cursor("pointer").event("dblclick",onDoubleClick);this._ensurePropEvents(pvMark)},_isDoubleClickable:function(keyArgs){var options=keyArgs||this.chart.options;return options.clickable&&!!this.doubleClickAction},_handleDoubleClick:function(pvMark,ev){if(!this._isDoubleClickable()){return}this._ignoreClicks=2;var sign=pvMark.sign;if(!sign||sign.isDoubleClickable()){var context=this._getContext(pvMark,ev);this._onDoubleClick(context)}},_onDoubleClick:function(context){var handler=this.doubleClickAction;if(handler){if(this.compatVersion()<=1){this._onV1DoubleClick(context,handler)}else{handler.call(context,context.scene)}}},_onV1DoubleClick:function(context,handler){handler.call(context.pvMark,context.getV1Series(),context.getV1Category(),context.getV1Value(),context.event,context.getV1Datum())},_isClickable:function(){return this.chart.options.clickable&&!!this.clickAction},_shouldHandleClick:function(){return this.chart._canSelectWithClick()||this._isClickable()},_handleClick:function(pvMark,ev){if(!this._shouldHandleClick()){return}var options=this.chart.options,context;if(!this.doubleClickAction){context=this._getContext(pvMark,ev);this._handleClickCore(context)}else{var myself=this;context=this._createContext(pvMark,ev);window.setTimeout(function(){myself._handleClickCore.call(myself,context)},options.doubleClickMaxDelay||300)}},_handleClickCore:function(context){if(this._ignoreClicks){this._ignoreClicks--}else{var sign=context.sign;if(!sign||sign.isClickable()){this._onClick(context)}if((sign&&sign.isSelectable())||(!sign&&this.chart.options.selectable&&context.scene.datum)){this._onSelect(context)}}},_onClick:function(context){var handler=this.clickAction;if(handler){if(this.compatVersion()<=1){this._onV1Click(context,handler)}else{handler.call(context,context.scene)}}},_onV1Click:function(context,handler){handler.call(context.pvMark,context.getV1Series(),context.getV1Category(),context.getV1Value(),context.event,context.getV1Datum())},_onSelect:function(context){var datums=context.scene.datums().array();if(datums.length){var chart=this.chart;chart._updatingSelections(function(){datums=chart._onUserSelection(datums);if(datums&&datums.length){if(chart.options.ctrlSelectMode&&!context.event.ctrlKey){chart.data.replaceSelected(datums)}else{pvc.data.Data.toggleSelected(datums)}}},this)}},isRubberBandSelecting:function(){return this.topRoot._isRubberBandSelecting},_initRubberBand:function(){var myself=this,chart=this.chart,options=chart.options,data=chart.data;var dMin2=4;this._isRubberBandSelecting=false;var rubberPvParentPanel=this.pvRootPanel||this.pvPanel.paddingPanel,toScreen,rb;var selectBar=this.selectBar=new pvc.visual.Bar(this,rubberPvParentPanel,{extensionId:'rubberBand',normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true}).override('defaultStrokeWidth',function(){return 1.5}).override('defaultColor',function(type){return type==='stroke'?'#86fe00':'rgba(203, 239, 163, 0.6)'}).override('interactiveColor',function(color){return color}).pvMark.lock('visible',function(){return!!rb}).lock('left',function(){return rb.x}).lock('right').lock('top',function(){return rb.y}).lock('bottom').lock('width',function(){return rb.dx}).lock('height',function(){return rb.dy}).lock('cursor').lock('events','none');if(!this._getExtensionAbs('base','fillStyle')){rubberPvParentPanel.fillStyle(pvc.invisibleFill)}rubberPvParentPanel.lock('events','all');var scene=new pvc.visual.Scene(null,{panel:this});scene.x=scene.y=scene.dx=scene.dy=0;var selectionEndedDate;rubberPvParentPanel.lock('data',[scene]).event('mousedown',pv.Behavior.select().autoRender(false)).event('select',function(){if(!rb){if(myself.isAnimating()){return}if(scene.dx*scene.dx+scene.dy*scene.dy<=dMin2){return}rb=new pv.Shape.Rect(scene.x,scene.y,scene.dx,scene.dy);myself._isRubberBandSelecting=true;if(!toScreen){toScreen=rubberPvParentPanel.toScreenTransform()}myself.rubberBand=rb.apply(toScreen)}else{rb=new pv.Shape.Rect(scene.x,scene.y,scene.dx,scene.dy)}selectBar.render()}).event('selectend',function(){if(rb){var ev=arguments[arguments.length-1];if(!toScreen){toScreen=rubberPvParentPanel.toScreenTransform()}var rbs=rb.apply(toScreen);rb=null;myself._isRubberBandSelecting=false;selectBar.render();try{myself._processRubberBand(rbs,ev,{allowAdditive:true})}finally{selectionEndedDate=new Date()}}});if(options.clearSelectionMode==='emptySpaceClick'){rubberPvParentPanel.event("click",function(){if(selectionEndedDate){var timeSpan=new Date()-selectionEndedDate;if(timeSpan<300){selectionEndedDate=null;return}}if(data.owner.clearSelected()){myself.chart.updateSelections()}})}},_processRubberBand:function(rb,ev,keyArgs){this.rubberBand=rb;try{this._onRubberBandSelectionEnd(ev,keyArgs)}finally{this.rubberBand=null}},_onRubberBandSelectionEnd:function(ev,keyArgs){if(pvc.debug>=10){this._log("rubberBand "+pvc.stringify(this.rubberBand))}keyArgs=Object.create(keyArgs||{});keyArgs.toggle=false;var datums=this._getDatumsOnRubberBand(ev,keyArgs);if(datums){var allowAdditive=def.get(keyArgs,'allowAdditive',true);var chart=this.chart;chart._updatingSelections(function(){var clearBefore=!allowAdditive||(!ev.ctrlKey&&chart.options.ctrlSelectMode);if(clearBefore){chart.data.owner.clearSelected();pvc.data.Data.setSelected(datums,true)}else if(keyArgs.toggle){pvc.data.Data.toggleSelected(datums)}else{pvc.data.Data.setSelected(datums,true)}})}},_getDatumsOnRubberBand:function(ev,keyArgs){var datumMap=new def.Map();this._getDatumsOnRect(datumMap,this.rubberBand,keyArgs);var datums=datumMap.values();if(datums.length){datums=this.chart._onUserSelection(datums);if(datums&&!datums.length){datums=null}}return datums},_getDatumsOnRect:function(datumMap,rect,keyArgs){this._getOwnDatumsOnRect(datumMap,rect,keyArgs);if(this._children){this._children.forEach(function(child){child._getDatumsOnRect(datumMap,rect,keyArgs)},this)}},_getOwnDatumsOnRect:function(datumMap,rect,keyArgs){var any=false;if(this.isVisible){var pvMarks=this._getSelectableMarks();if(pvMarks&&pvMarks.length){pvMarks.forEach(function(pvMark){this._eachMarkDatumOnRect(pvMark,rect,function(datum){datumMap.set(datum.id,datum);any=true},this,def.get(keyArgs,'markSelectionMode'))},this)}}return any},_eachMarkDatumOnRect:function(pvMark,rect,fun,ctx,selectionMode){var sign=pvMark.sign;if(sign&&!sign.isSelectable()){return}if(selectionMode==null){selectionMode=def.get(pvMark,'rubberBandSelectionMode','partial')}var useCenter=(selectionMode==='center');pvMark.eachInstanceWithData(function(scenes,index,toScreen){var shape=pvMark.getShape(scenes,index);shape=(useCenter?shape.center():shape).apply(toScreen);processShape.call(this,shape,scenes[index],index)},this);function processShape(shape,instance,index){if(shape.intersectsRect(rect)){var cccScene=instance.data;if(cccScene&&cccScene.datum){var group=cccScene.group;var datums=group?group._datums:def.array.as(cccScene.datum);if(datums){datums.forEach(function(datum){if(!datum.isNull){if(pvc.debug>=20){this._log("Rubbered Datum.key="+datum.key+": "+pvc.stringify(shape)+" mark type: "+pvMark.type+" index="+index)}fun.call(ctx,datum)}},this)}}}}},isAnchorTopOrBottom:function(anchor){if(!anchor){anchor=this.anchor}return anchor==="top"||anchor==="bottom"},anchorOrtho:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.relativeAnchor[anchor]},anchorOrthoMirror:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.relativeAnchorMirror[anchor]},anchorOpposite:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.oppositeAnchor[anchor]},anchorLength:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.parallelLength[anchor]},anchorOrthoLength:function(anchor){if(!anchor){anchor=this.anchor}return pvc.BasePanel.orthogonalLength[anchor]},isOrientationVertical:function(orientation){return this.chart.isOrientationVertical(orientation)},isOrientationHorizontal:function(orientation){return this.chart.isOrientationHorizontal(orientation)}}).addStatic({relativeAnchor:{top:"left",bottom:"left",left:"bottom",right:"bottom"},leftBottomAnchor:{top:"bottom",bottom:"bottom",left:"left",right:"left"},leftTopAnchor:{top:"top",bottom:"top",left:"left",right:"left"},horizontalAlign:{top:"right",bottom:"left",middle:"center",right:"right",left:"left",center:"center"},verticalAlign:{top:"top",bottom:"bottom",middle:"middle",right:"bottom",left:"top",center:"middle"},verticalAlign2:{top:"top",bottom:"bottom",middle:"middle",right:"top",left:"bottom",center:"middle"},relativeAnchorMirror:{top:"right",bottom:"right",left:"top",right:"top"},oppositeAnchor:{top:"bottom",bottom:"top",left:"right",right:"left"},parallelLength:{top:"width",bottom:"width",right:"height",left:"height"},orthogonalLength:{top:"height",bottom:"height",right:"width",left:"width"},oppositeLength:{width:"height",height:"width"}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBoxplotChart.js b/pacotes/ccc2/compacto/pvcBoxplotChart.js deleted file mode 100755 index a1128eb..0000000 --- a/pacotes/ccc2/compacto/pvcBoxplotChart.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.BoxplotChart',pvc.CategoricalAbstract).add({_processOptionsCore:function(options){this.base.apply(this,arguments);options.stacked=false},_initVisualRoles:function(){this.base();var roleSpecBase={isMeasure:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number};[{name:'median',label:'Median',defaultDimension:'median',isRequired:true},{name:'lowerQuartil',label:'Lower Quartil',defaultDimension:'lowerQuartil'},{name:'upperQuartil',label:'Upper Quartil',defaultDimension:'upperQuartil'},{name:'minimum',label:'Minimum',defaultDimension:'minimum'},{name:'maximum',label:'Maximum',defaultDimension:'maximum'}].forEach(function(info){this._addVisualRole(info.name,def.create(roleSpecBase,info))},this)},_getTranslationClass:function(translOptions){return def.type(this.base(translOptions)).add(pvc.data.BoxplotChartTranslationOper)},_initPlotsCore:function(){new pvc.visual.BoxPlot(this);if(this.options.plot2){this._animatable=true;new pvc.visual.PointPlot(this,{name:'plot2',defaults:{LinesVisible:true,DotsVisible:true,OrthoRole:'median',ColorAxis:2},fixed:{OrthoAxis:1}})}},_bindAxes:function(hasMultiRole){this.base(hasMultiRole);var typeAxes=this.axesByType.ortho;if(typeAxes){typeAxes.forEach(function(axis){axis.option.defaults({Offset:0.02})})}},_createPlotPanels:function(parentPanel,baseOptions){var plots=this.plots;var boxPlot=plots.box;var boxPanel=new pvc.BoxplotPanel(this,parentPanel,boxPlot,Object.create(baseOptions));this.bpChartPanel=boxPanel;var plot2Plot=plots.plot2;if(plot2Plot){if(pvc.debug>=3){this._log("Creating Point panel.")}var pointPanel=new pvc.PointPanel(this,parentPanel,plot2Plot,Object.create(baseOptions));pointPanel._v1DimRoleName.value=plot2Plot.option('OrthoRole')}},defaults:{crosstabMode:false}}).addStatic({measureRolesNames:['median','lowerQuartil','upperQuartil','minimum','maximum']}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBoxplotPanel.js b/pacotes/ccc2/compacto/pvcBoxplotPanel.js deleted file mode 100755 index 75b7575..0000000 --- a/pacotes/ccc2/compacto/pvcBoxplotPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.BoxplotPanel',pvc.CategoricalAbstractPanel).init(function(chart,parent,plot,options){this.base(chart,parent,plot,options);this.boxSizeRatio=plot.option('BoxSizeRatio');this.maxBoxSize=plot.option('BoxSizeMax')}).add({plotType:'box',anchor:'fill',_v1DimRoleName:{'value':'median'},_createCore:function(){this.base();var rootScene=this._buildScene();var a_bottom=this.isOrientationVertical()?"bottom":"left",a_left=this.anchorOrtho(a_bottom),a_width=this.anchorLength(a_bottom),a_height=this.anchorOrthoLength(a_bottom);function defaultColor(type){var color=this.base(type);return type==='stroke'?color.darker(1):color}var extensionIds=['panel'];if(this.compatVersion()<=1){extensionIds.push('')}this.pvBoxPanel=new pvc.visual.Panel(this,this.pvPanel,{extensionId:extensionIds}).lock('data',rootScene.childNodes).lockMark(a_left,function(scene){var catVar=scene.vars.category;return catVar.x-catVar.width/2}).pvMark[a_width](function(scene){return scene.vars.category.width});function setupRuleWhisker(rule){rule.lock(a_left,function(){return this.pvMark.parent[a_width]()/2}).override('defaultColor',defaultColor);return rule}this.pvRuleWhiskerUpper=setupRuleWhisker(new pvc.visual.Rule(this,this.pvBoxPanel,{extensionId:'boxRuleWhisker',freePosition:true,noHover:false,noSelect:false,noClick:false,noDoubleClick:false})).intercept('visible',function(scene){return scene.vars.category.showRuleWhiskerUpper&&this.delegateExtension(true)}).lock(a_bottom,function(scene){return scene.vars.category.ruleWhiskerUpperBottom}).lock(a_height,function(scene){return scene.vars.category.ruleWhiskerUpperHeight}).pvMark;this.pvRuleWhiskerLower=setupRuleWhisker(new pvc.visual.Rule(this,this.pvBoxPanel,{extensionId:'boxRuleWhisker',freePosition:true,noHover:false,noSelect:false,noClick:false,noDoubleClick:false})).intercept('visible',function(scene){return scene.vars.category.showRuleWhiskerBelow&&this.delegateExtension(true)}).lock(a_bottom,function(scene){return scene.vars.category.ruleWhiskerLowerBottom}).lock(a_height,function(scene){return scene.vars.category.ruleWhiskerLowerHeight}).pvMark;function setupHCateg(sign){sign.lock(a_left,function(scene){return scene.vars.category.boxLeft}).lock(a_width,function(scene){return scene.vars.category.boxWidth});return sign}this.pvBar=setupHCateg(new pvc.visual.Bar(this,this.pvBoxPanel,{extensionId:'boxBar',freePosition:true,normalStroke:true})).intercept('visible',function(scene){return scene.vars.category.showBox&&this.delegateExtension(true)}).lock(a_bottom,function(scene){return scene.vars.category.boxBottom}).lock(a_height,function(scene){return scene.vars.category.boxHeight}).override('defaultColor',defaultColor).override('defaultStrokeWidth',def.fun.constant(1)).pvMark;function setupHRule(rule){setupHCateg(rule);rule.override('defaultColor',defaultColor);return rule}this.pvRuleMin=setupHRule(new pvc.visual.Rule(this,this.pvBoxPanel,{extensionId:'boxRuleMin',freePosition:true,noHover:false,noSelect:false,noClick:false,noDoubleClick:false})).intercept('visible',function(){return this.scene.vars.minimum.value!=null&&this.delegateExtension(true)}).lock(a_bottom,function(){return this.scene.vars.minimum.position}).pvMark;this.pvRuleMax=setupHRule(new pvc.visual.Rule(this,this.pvBoxPanel,{extensionId:'boxRuleMax',freePosition:true,noHover:false,noSelect:false,noClick:false,noDoubleClick:false})).intercept('visible',function(){return this.scene.vars.maximum.value!=null&&this.delegateExtension(true)}).lock(a_bottom,function(){return this.scene.vars.maximum.position}).pvMark;this.pvRuleMedian=setupHRule(new pvc.visual.Rule(this,this.pvBoxPanel,{extensionId:'boxRuleMedian',freePosition:true,noHover:false,noSelect:false,noClick:false,noDoubleClick:false})).intercept('visible',function(){return this.scene.vars.median.value!=null&&this.delegateExtension(true)}).lock(a_bottom,function(){return this.scene.vars.median.position}).override('defaultStrokeWidth',def.fun.constant(2)).pvMark},renderInteractive:function(){this.pvBoxPanel.render()},_getSelectableMarks:function(){return[this.pvBar]},_buildScene:function(){var chart=this.chart,measureRolesDimNames=def.query(chart.measureVisualRoles()).object({name:function(role){return role.name},value:function(role){return role.firstDimensionName()}}),visibleKeyArgs={visible:true,zeroIfNone:false},data=this.visibleData(),rootScene=new pvc.visual.Scene(null,{panel:this,group:data}),baseScale=this.axes.base.scale,bandWidth=baseScale.range().band,boxWidth=Math.min(bandWidth*this.boxSizeRatio,this.maxBoxSize),orthoScale=this.axes.ortho.scale,colorVarHelper=new pvc.visual.RoleVarHelper(chart,chart._colorRole);data.children().each(createCategScene,this);return rootScene;function createCategScene(categData){var categScene=new pvc.visual.Scene(rootScene,{group:categData});var vars=categScene.vars;vars.series=new pvc.visual.ValueLabelVar(null,"");var catVar=vars.category=new pvc.visual.ValueLabelVar(categData.value,categData.label);def.set(catVar,'group',categData,'x',baseScale(categData.value),'width',bandWidth,'boxWidth',boxWidth,'boxLeft',bandWidth/2-boxWidth/2);chart.measureVisualRoles().forEach(function(role){var dimName=measureRolesDimNames[role.name],svar;if(dimName){var dim=categData.dimensions(dimName),value=dim.sum(visibleKeyArgs);svar=new pvc.visual.ValueLabelVar(value,dim.format(value));svar.position=orthoScale(value)}else{svar=new pvc.visual.ValueLabelVar(null,"");svar.position=null}vars[role.name]=svar});colorVarHelper.onNewScene(categScene,true);var hasMin=vars.minimum.value!=null,hasLower=vars.lowerQuartil.value!=null,hasMedian=vars.median.value!=null,hasUpper=vars.upperQuartil.value!=null,bottom,top;var show=hasLower||hasUpper;if(show){bottom=hasLower?vars.lowerQuartil.position:hasMedian?vars.median.position:vars.upperQuartil.position;top=hasUpper?vars.upperQuartil.position:hasMedian?vars.median.position:vars.lowerQuartil.position;show=(top!==bottom);if(show){catVar.boxBottom=bottom;catVar.boxHeight=top-bottom}}catVar.showBox=show;show=vars.maximum.value!=null;if(show){bottom=hasUpper?vars.upperQuartil.position:hasMedian?vars.median.position:hasLower?vars.lowerQuartil.position:hasMin?vars.minimum.position:null;show=bottom!=null;if(show){catVar.ruleWhiskerUpperBottom=bottom;catVar.ruleWhiskerUpperHeight=vars.maximum.position-bottom}}catVar.showRuleWhiskerUpper=show;show=hasMin;if(show){top=hasLower?vars.lowerQuartil.position:hasMedian?vars.median.position:hasUpper?vars.upperQuartil.position:null;show=top!=null;if(show){bottom=vars.minimum.position;catVar.ruleWhiskerLowerHeight=top-bottom;catVar.ruleWhiskerLowerBottom=bottom}}catVar.showRuleWhiskerBelow=show}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcBulletChart.js b/pacotes/ccc2/compacto/pvcBulletChart.js deleted file mode 100755 index 9d6e778..0000000 --- a/pacotes/ccc2/compacto/pvcBulletChart.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.BulletChart',pvc.BaseChart).init(function(options){options=options||{};var dimGroups=options.dimensionGroups||(options.dimensionGroups={});var rangeDimGroup=dimGroups.range||(dimGroups.range={});if(rangeDimGroup.valueType===undefined){rangeDimGroup.valueType=Number}var markerDimGroup=dimGroups.marker||(dimGroups.marker={});if(markerDimGroup.valueType===undefined){markerDimGroup.valueType=Number}this.base(options)}).add({bulletChartPanel:null,allowNoData:true,_processOptionsCore:function(options){this.base(options);options.legend=false;options.selectable=false},_initVisualRoles:function(){this.base();this._addVisualRole('title',{defaultDimension:'title*'});this._addVisualRole('subTitle',{defaultDimension:'subTitle*'});this._addVisualRole('value',{isMeasure:true,requireIsDiscrete:false,valueType:Number,defaultDimension:'value*'});this._addVisualRole('marker',{isMeasure:true,requireIsDiscrete:false,valueType:Number,defaultDimension:'marker*'});this._addVisualRole('range',{isMeasure:true,requireIsDiscrete:false,valueType:Number,defaultDimension:'range*'})},_createTranslation:function(translOptions){var translation=this.base(translOptions),size=translation.virtualItemSize();if(size){switch(size){case 1:translation.defReader({names:'value'});break;case 2:translation.defReader({names:['title','value']});break;case 3:translation.defReader({names:['title','value','marker']});break;default:translation.defReader({names:['title','subTitle','value','marker']});if(size>4){translation.defReader({names:'range',indexes:pv.range(4,size)})}break}}return translation},_initPlotsCore:function(hasMultiRole){new pvc.visual.BulletPlot(this)},_preRenderContent:function(contentOptions){var bulletPlot=this.plots.bullet;this.bulletChartPanel=new pvc.BulletChartPanel(this,this.basePanel,bulletPlot,def.create(contentOptions,{tooltipEnabled:this._tooltipEnabled}))},defaults:{compatVersion:1,orientation:'horizontal',bulletSize:30,bulletSpacing:50,bulletMargin:100,bulletTitle:"Title",bulletSubtitle:"",bulletTitlePosition:"left",tooltipFormat:function(s,c,v){return this.chart.options.valueFormat(v)},crosstabMode:false,seriesInRows:false}});def.type('pvc.BulletChartPanel',pvc.PlotPanel).add({pvBullets:null,pvBullet:null,data:null,onSelectionChange:null,_createCore:function(layoutInfo){var chart=this.chart,options=chart.options,data=this.buildData();var anchor=options.orientation=="horizontal"?"left":"bottom";var size,angle,align,titleLeftOffset,titleTopOffset,ruleAnchor,leftPos,topPos,titleSpace;if(options.orientation=="horizontal"){size=layoutInfo.clientSize.width-this.chart.options.bulletMargin-20;angle=0;switch(options.bulletTitlePosition){case'top':leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;align='left';titleTopOffset=-12;titleSpace=parseInt(options.titleSize/2,10);break;case'bottom':leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;align='left';titleTopOffset=options.bulletSize+32;titleSpace=0;break;case'right':leftPos=5;titleLeftOffset=size+5;align='left';titleTopOffset=parseInt(options.bulletSize/2,10);titleSpace=0;break;case'left':default:leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;titleTopOffset=parseInt(options.bulletSize/2,10);align='right';titleSpace=0}ruleAnchor="bottom";topPos=function(){return(this.index*(options.bulletSize+options.bulletSpacing))+titleSpace}}else{size=layoutInfo.clientSize.height-this.chart.options.bulletMargin-20;switch(options.bulletTitlePosition){case'top':leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;align='left';titleTopOffset=-20;angle=0;topPos=undefined;break;case'bottom':leftPos=this.chart.options.bulletMargin;titleLeftOffset=0;align='left';titleTopOffset=size+20;angle=0;topPos=20;break;case'right':leftPos=5;titleLeftOffset=this.chart.options.bulletSize+40;align='left';titleTopOffset=size;angle=-Math.PI/2;topPos=undefined;break;case'left':default:leftPos=this.chart.options.bulletMargin;titleLeftOffset=-12;titleTopOffset=this.height-this.chart.options.bulletMargin-20;align='left';angle=-Math.PI/2;topPos=undefined}ruleAnchor="right";leftPos=function(){return options.bulletMargin+this.index*(options.bulletSize+options.bulletSpacing)}}this.pvBullets=this.pvPanel.add(pv.Panel).data(data)[pvc.BasePanel.orthogonalLength[anchor]](size)[pvc.BasePanel.parallelLength[anchor]](this.chart.options.bulletSize).margin(20).left(leftPos).top(topPos);this.pvBullet=this.pvBullets.add(pv.Layout.Bullet).orient(anchor).ranges(function(d){return d.ranges}).measures(function(d){return d.measures}).markers(function(d){return d.markers});if(options.clickable&&this.clickAction){var me=this;this.pvBullet.cursor("pointer").event("click",function(d){var s=d.title;var c=d.subtitle;var ev=pv.event;return me.clickAction(s,c,d.measures,ev)})}this.pvBulletRange=this.pvBullet.range.add(pv.Bar);this.pvBulletMeasure=this.pvBullet.measure.add(pv.Bar).text(function(v,d){return d.formattedMeasures[this.index]});this.pvBulletMarker=this.pvBullet.marker.add(pv.Dot).shape("square").fillStyle("white").text(function(v,d){return d.formattedMarkers[this.index]});if(this.tooltipEnabled){var myself=this;this.pvBulletMeasure.localProperty('tooltip').tooltip(function(v,d){var s=d.title;var c=d.subtitle;return chart.options.tooltipFormat.call(myself,s,c,v)});this.pvBulletMarker.localProperty('tooltip').tooltip(function(v,d){var s=d.title;var c=d.subtitle;return chart.options.tooltipFormat.call(myself,s,c,v)});this.pvBulletMeasure.event("mouseover",pv.Behavior.tipsy(this.chart._tooltipOptions));this.pvBulletMarker.event("mouseover",pv.Behavior.tipsy(this.chart._tooltipOptions))}this.pvBulletRule=this.pvBullet.tick.add(pv.Rule);this.pvBulletRuleLabel=this.pvBulletRule.anchor(ruleAnchor).add(pv.Label).text(this.pvBullet.x.tickFormat);this.pvBulletTitle=this.pvBullet.anchor(anchor).add(pv.Label).font("bold 12px sans-serif").textAngle(angle).left(-10).textAlign(align).textBaseline("bottom").left(titleLeftOffset).top(titleTopOffset).text(function(d){return d.formattedTitle});this.pvBulletSubtitle=this.pvBullet.anchor(anchor).add(pv.Label).textStyle("#666").textAngle(angle).textAlign(align).textBaseline("top").left(titleLeftOffset).top(titleTopOffset).text(function(d){return d.formattedSubtitle});var doubleClickAction=(typeof(options.axisDoubleClickAction)=='function')?function(d,e){options.axisDoubleClickAction(d,e)}:null;if(options.clickable&&doubleClickAction){this.pvBulletTitle.cursor("pointer").events('all').event("dblclick",function(d){doubleClickAction(d,arguments[arguments.length-1])});this.pvBulletSubtitle.cursor("pointer").events('all').event("dblclick",function(d){doubleClickAction(d,arguments[arguments.length-1])})}},applyExtensions:function(){this.base();this.extend(this.pvBullets,"bulletsPanel");this.extend(this.pvBullet,"bulletPanel");this.extend(this.pvBulletRange,"bulletRange");this.extend(this.pvBulletMeasure,"bulletMeasure");this.extend(this.pvBulletMarker,"bulletMarker");this.extend(this.pvBulletRule,"bulletRule");this.extend(this.pvBulletRuleLabel,"bulletRuleLabel");this.extend(this.pvBulletTitle,"bulletTitle");this.extend(this.pvBulletSubtitle,"bulletSubtitle")},_getExtensionId:function(){return[{abs:'content'}].concat(this.base())},buildData:function(){var data,chart=this.chart,options=chart.options,titleRole=chart.visualRoles('title'),titleGrouping=titleRole.grouping,subTitleRole=chart.visualRoles('subTitle'),subTitleGrouping=subTitleRole.grouping,valueRole=chart.visualRoles('value'),valueGrouping=valueRole.grouping,markerRole=chart.visualRoles('marker'),markerGrouping=markerRole.grouping,rangeRole=chart.visualRoles('range'),rangeGrouping=rangeRole.grouping;var defaultData={title:options.bulletTitle,formattedTitle:options.bulletTitle,subtitle:options.bulletSubtitle,formattedSubtitle:options.bulletSubtitle,ranges:def.array.to(options.bulletRanges)||[],measures:def.array.to(options.bulletMeasures)||[],markers:def.array.to(options.bulletMarkers)||[]};def.set(defaultData,'formattedRanges',defaultData.ranges.map(String),'formattedMeasures',defaultData.measures.map(String),'formattedMarkers',defaultData.markers.map(String));if(!valueGrouping&&!titleGrouping&&!markerGrouping&&!subTitleGrouping&&!rangeGrouping){data=[defaultData]}else{data=chart.data.datums().select(function(datum){var d=Object.create(defaultData),view;if(valueGrouping){view=valueGrouping.view(datum);d.measures=view.values();d.formattedMeasures=view.labels()}if(titleGrouping){view=titleGrouping.view(datum);d.title=view.value;d.formattedTitle=view.label}if(subTitleGrouping){view=subTitleGrouping.view(datum);d.subtitle=view.value;d.formattedSubtitle=view.label}if(markerGrouping){view=markerGrouping.view(datum);d.markers=view.values();d.formattedMarkers=view.labels()}if(rangeGrouping){view=rangeGrouping.view(datum);d.ranges=view.values();d.formattedRanges=view.labels()}return d},this).array()}return data}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcCartesianAbstract.js b/pacotes/ccc2/compacto/pvcCartesianAbstract.js deleted file mode 100755 index 603e84f..0000000 --- a/pacotes/ccc2/compacto/pvcCartesianAbstract.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.CartesianAbstract',pvc.BaseChart).init(function(options){this.axesPanels={};this.base(options)}).add({_gridDockPanel:null,axesPanels:null,yAxisPanel:null,xAxisPanel:null,secondXAxisPanel:null,secondYAxisPanel:null,yScale:null,xScale:null,_getSeriesRoleSpec:function(){return{isRequired:true,defaultDimension:'series*',autoCreateDimension:true,requireIsDiscrete:true}},_getColorRoleSpec:function(){return{isRequired:true,defaultDimension:'color*',defaultSourceRole:'series',requireIsDiscrete:true}},_collectPlotAxesDataCells:function(plot,dataCellsByAxisTypeThenIndex){this.base(plot,dataCellsByAxisTypeThenIndex);if(plot.option.isDefined('BaseAxis')){var baseDataCellsByAxisIndex=def.array.lazy(dataCellsByAxisTypeThenIndex,'base');def.array.lazy(baseDataCellsByAxisIndex,plot.option('BaseAxis')-1).push({plot:plot,role:this.visualRoles(plot.option('BaseRole')),dataPartValue:plot.option('DataPart')})}if(plot.option.isDefined('OrthoAxis')){var trend=plot.option('Trend');var isStacked=plot.option.isDefined('Stacked')?plot.option('Stacked'):undefined;var orthoDataCellsByAxisIndex=def.array.lazy(dataCellsByAxisTypeThenIndex,'ortho');var orthoRoleNames=def.array.to(plot.option('OrthoRole'));var dataCellBase={dataPartValue:plot.option('DataPart'),isStacked:isStacked,trend:trend,nullInterpolationMode:plot.option('NullInterpolationMode')};var orthoDataCells=def.array.lazy(orthoDataCellsByAxisIndex,plot.option('OrthoAxis')-1);orthoRoleNames.forEach(function(orthoRoleName){var dataCell=Object.create(dataCellBase);dataCell.role=this.visualRoles(orthoRoleName);orthoDataCells.push(dataCell)},this)}},_addAxis:function(axis){this.base(axis);switch(axis.type){case'base':case'ortho':this.axes[axis.orientedId]=axis;if(axis.v1SecondOrientedId){this.axes[axis.v1SecondOrientedId]=axis}break}return this},_generateTrendsDataCell:function(dataCell){var trend=dataCell.trend;if(trend){var trendInfo=pvc.trends.get(trend.type);var newDatums=[];this._generateTrendsDataCellCore(newDatums,dataCell,trendInfo);if(newDatums.length){this.data.owner.add(newDatums)}}},_generateTrendsDataCellCore:function(dataCell,trendInfo){},_setAxesScales:function(hasMultiRole){this.base(hasMultiRole);if(!hasMultiRole||this.parent){['base','ortho'].forEach(function(type){var axisOfType=this.axesByType[type];if(axisOfType){axisOfType.forEach(this._createAxisScale,this)}},this)}},_createAxisScale:function(axis){var isOrtho=axis.type==='ortho';var isCart=isOrtho||axis.type==='base';var scale=this._createScaleByAxis(axis);if(scale.isNull&&pvc.debug>=3){this._log(def.format("{0} scale for axis '{1}'- no data",[axis.scaleType,axis.id]))}scale=axis.setScale(scale).scale;if(isCart){if(isOrtho&&axis.index===1){this.secondScale=scale}else if(!axis.index){this[axis.orientation+'Scale']=scale}}return scale},_createScaleByAxis:function(axis){var createScale=this['_create'+def.firstUpperCase(axis.scaleType)+'ScaleByAxis'];return createScale.call(this,axis)},_preRenderContent:function(contentOptions){this._createFocusWindow();this._gridDockPanel=new pvc.CartesianGridDockingPanel(this,this.basePanel,{margins:contentOptions.margins,paddings:contentOptions.paddings});['base','ortho'].forEach(function(type){var typeAxes=this.axesByType[type];if(typeAxes){def.query(typeAxes).reverse().each(function(axis){this._createAxisPanel(axis)},this)}},this);this._createPlotPanels(this._gridDockPanel,{clickAction:contentOptions.clickAction,doubleClickAction:contentOptions.doubleClickAction})},_createFocusWindow:function(){if(this._canSelectWithFocusWindow()){var fwData;var fw=this.focusWindow;if(fw){fwData=fw._exportData()}fw=this.focusWindow=new pvc.visual.CartesianFocusWindow(this);if(fwData){fw._importData(fwData)}fw._initFromOptions()}else if(this.focusWindow){delete this.focusWindow}},_createAxisPanel:function(axis){if(axis.option('Visible')){var titlePanel;var title=axis.option('Title');if(!def.empty(title)){titlePanel=new pvc.AxisTitlePanel(this,this._gridDockPanel,axis,{title:title,font:axis.option('TitleFont')||axis.option('Font'),anchor:axis.option('Position'),align:axis.option('TitleAlign'),margins:axis.option('TitleMargins'),paddings:axis.option('TitlePaddings'),titleSize:axis.option('TitleSize'),titleSizeMax:axis.option('TitleSizeMax')})}var panel=new pvc.AxisPanel(this,this._gridDockPanel,axis,{anchor:axis.option('Position'),size:axis.option('Size'),sizeMax:axis.option('SizeMax'),clickAction:axis.option('ClickAction'),doubleClickAction:axis.option('DoubleClickAction'),useCompositeAxis:axis.option('Composite'),font:axis.option('Font'),labelSpacingMin:axis.option('LabelSpacingMin'),tickExponentMin:axis.option('TickExponentMin'),tickExponentMax:axis.option('TickExponentMax'),grid:axis.option('Grid'),gridCrossesMargin:axis.option('GridCrossesMargin'),ruleCrossesMargin:axis.option('RuleCrossesMargin'),zeroLine:axis.option('ZeroLine'),domainRoundMode:axis.option('DomainRoundMode'),desiredTickCount:axis.option('DesiredTickCount'),showTicks:axis.option('Ticks'),showMinorTicks:axis.option('MinorTicks')});if(titlePanel){panel.titlePanel=titlePanel}this.axesPanels[axis.id]=panel;this.axesPanels[axis.orientedId]=panel;if(axis.index<=1&&axis.v1SecondOrientedId){this[axis.v1SecondOrientedId+'AxisPanel']=panel}return panel}},_createDiscreteScaleByAxis:function(axis){var dataPartValues=axis.dataCells.map(function(dataCell){return dataCell.dataPartValue});var baseData=this.visibleData(dataPartValues,{ignoreNulls:false});var data=baseData&&baseData.flattenBy(axis.role);var scale=new pv.Scale.ordinal();if(!data||!data.count()){scale.isNull=true}else{var values=data.children().select(function(child){return def.nullyTo(child.value,"")}).array();scale.domain(values)}return scale},_createTimeSeriesScaleByAxis:function(axis){var extent=this._getContinuousVisibleExtent(axis);var scale=new pv.Scale.linear();if(!extent){scale.isNull=true}else{var dMin=extent.min;var dMax=extent.max;if((dMax-dMin)===0){dMax=new Date(dMax.getTime()+3600000)}scale.domain(dMin,dMax);scale.minLocked=extent.minLocked;scale.maxLocked=extent.maxLocked}return scale},_createNumericScaleByAxis:function(axis){var extent=this._getContinuousVisibleExtentConstrained(axis);var scale=new pv.Scale.linear();if(!extent){scale.isNull=true}else{var tmp;var dMin=extent.min;var dMax=extent.max;if(dMin>dMax){tmp=dMin;dMin=dMax;dMax=tmp}var originIsZero=axis.option('OriginIsZero');if(originIsZero){if(dMin===0){extent.minLocked=true}else if(dMax===0){extent.maxLocked=true}else if((dMin*dMax)>0){if(dMin>0){if(!extent.minLocked){extent.minLocked=true;dMin=0}}else{if(!extent.maxLocked){extent.maxLocked=true;dMax=0}}}}if(dMin>dMax){tmp=dMin;dMin=dMax;dMax=tmp}if(dMax-dMin<=1e-12){if(!extent.minLocked){dMin=dMin!==0?(dMin*0.99):-0.1}if(!extent.maxLocked||extent.minLocked){dMax=dMax!==0?dMax*1.01:0.1}}scale.domain(dMin,dMax);scale.minLocked=extent.minLocked;scale.maxLocked=extent.maxLocked}return scale},_onLaidOut:function(){if(this.plotPanelList&&this.plotPanelList[0]){['base','ortho'].forEach(function(type){var axes=this.axesByType[type];if(axes){axes.forEach(this._setCartAxisScaleRange,this)}},this)}},_setCartAxisScaleRange:function(axis){var info=this.plotPanelList[0]._layoutInfo;var size=info.clientSize;var length=(axis.orientation==='x')?size.width:size.height;axis.setScaleRange(length);return axis.scale},_getAxesRoundingPaddings:function(){var axesPaddings={};var axesByType=this.axesByType;['base','ortho'].forEach(function(type){var typeAxes=axesByType[type];if(typeAxes){typeAxes.forEach(processAxis)}});return axesPaddings;function setSide(side,pct,locked){var value=axesPaddings[side];if(value==null||pct>value){axesPaddings[side]=pct;axesPaddings[side+'Locked']=locked}else if(locked){axesPaddings[side+'Locked']=locked}}function processAxis(axis){if(axis){var tickRoundPads=axis.getScaleRoundingPaddings();if(tickRoundPads){var isX=axis.orientation==='x';setSide(isX?'left':'bottom',tickRoundPads.begin,tickRoundPads.beginLocked);setSide(isX?'right':'top',tickRoundPads.end,tickRoundPads.endLocked)}}}},_warnSingleContinuousValueRole:function(valueRole){if(!valueRole.grouping.isSingleDimension){this._log("[WARNING] A linear scale can only be obtained for a single dimension role.")}if(valueRole.grouping.isDiscrete()){this._log("[WARNING] The single dimension of role '{0}' should be continuous.",[valueRole.name])}},_getContinuousVisibleExtentConstrained:function(axis,min,max){var minLocked=false;var maxLocked=false;if(min==null){min=axis.option('FixedMin');minLocked=(min!=null)}if(max==null){max=axis.option('FixedMax');maxLocked=(max!=null)}if(min==null||max==null){var baseExtent=this._getContinuousVisibleExtent(axis);if(!baseExtent){return null}if(min==null){min=baseExtent.min}if(max==null){max=baseExtent.max}}return{min:min,max:max,minLocked:minLocked,maxLocked:maxLocked}},_getContinuousVisibleExtent:function(valueAxis){var dataCells=valueAxis.dataCells;if(dataCells.length===1){return this._getContinuousVisibleCellExtent(valueAxis,dataCells[0])}return def.query(dataCells).select(function(dataCell){return this._getContinuousVisibleCellExtent(valueAxis,dataCell)},this).reduce(pvc.unionExtents,null)},_getContinuousVisibleCellExtent:function(valueAxis,valueDataCell){var valueRole=valueDataCell.role;this._warnSingleContinuousValueRole(valueRole);if(valueRole.name==='series'){throw def.error.notImplemented()}var useAbs=valueAxis.scaleUsesAbs();var data=this.visibleData(valueDataCell.dataPartValue);var extent=data&&data.dimensions(valueRole.firstDimensionName()).extent({abs:useAbs});if(extent){var minValue=extent.min.value;var maxValue=extent.max.value;return{min:(useAbs?Math.abs(minValue):minValue),max:(useAbs?Math.abs(maxValue):maxValue)}}},markEventDefaults:{strokeStyle:"#5BCBF5",lineWidth:"0.5",textStyle:"#5BCBF5",verticalOffset:10,verticalAnchor:"bottom",horizontalAnchor:"right",forceHorizontalAnchor:false,horizontalAnchorSwapLimit:80},markEvent:function(dateString,label,options){var baseScale=this.axes.base.scale;if(baseScale.type!=='timeSeries'){this._log("Attempting to mark an event on a non timeSeries chart");return this}var o=$.extend({},this.markEventDefaults,options);var d=pv.Format.date(this.options.timeSeriesFormat).parse(dateString);var dpos=baseScale(d),range=baseScale.range();if(dposrange[1]){this._log("Event outside the allowed range, returning");return this}var panel=this.plotPanelList[0].pvPanel;var h=this.yScale.range()[1];if(!o.forceHorizontalAnchor){var availableSize=o.horizontalAnchor=="right"?range[1]-dpos:dpos;if(availableSizevalue){hasAny=true;pctPaddings[side]=pct}}function processAxis(axis){var offset=axis&&axis.option('Offset');if(offset!=null&&offset>0&&offset<1){if(axis.orientation==='x'){setSide('left',offset);setSide('right',offset)}else{setSide('top',offset);setSide('bottom',offset)}}}var chartAxes=chart.axesByType;['base','ortho'].forEach(function(type){var typeAxes=chartAxes[type];if(typeAxes){typeAxes.forEach(processAxis)}});if(hasAny){this.offsetPaddings=pctPaddings}}).add({offsetPaddings:null,_calcLayout:function(layoutInfo){layoutInfo.requestPaddings=this._calcRequestPaddings(layoutInfo)},_calcRequestPaddings:function(layoutInfo){var reqPads;var offPads=this.offsetPaddings;if(offPads){var tickRoundPads=this.chart._getAxesRoundingPaddings();var clientSize=layoutInfo.clientSize;var pads=layoutInfo.paddings;pvc.Sides.names.forEach(function(side){var len_a=pvc.BasePanel.orthogonalLength[side];var clientLen=clientSize[len_a];var paddingLen=pads[len_a];var len=clientLen+paddingLen;if(!tickRoundPads[side+'Locked']){var offLen=len*(offPads[side]||0);var roundLen=clientLen*(tickRoundPads[side]||0);(reqPads||(reqPads={}))[side]=Math.max(offLen-roundLen,0)}},this)}return reqPads},_createCore:function(){this.pvPanel.zOrder(-10);var hideOverflow;var contentOverflow=this.chart.options.leafContentOverflow||'auto';if(contentOverflow==='auto'){hideOverflow=def.query(['ortho','base']).select(function(axisType){return this.axes[axisType]},this).any(function(axis){return axis.option('FixedMin')!=null||axis.option('FixedMax')!=null})}else{hideOverflow=(contentOverflow==='hidden')}if(hideOverflow){this.pvPanel.borderPanel.overflow('hidden')}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcCartesianGridDockingPanel.js b/pacotes/ccc2/compacto/pvcCartesianGridDockingPanel.js deleted file mode 100755 index bf496bb..0000000 --- a/pacotes/ccc2/compacto/pvcCartesianGridDockingPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.CartesianGridDockingPanel',pvc.GridDockingPanel).init(function(chart,parent,options){this.base(chart,parent,options);this._plotBgPanel=new pvc.PlotBgPanel(chart,this)}).add({_getExtensionId:function(){return!this.chart.parent?'content':'smallContent'},_createCore:function(layoutInfo){var chart=this.chart;var axes=chart.axes;var xAxis=axes.x;var yAxis=axes.y;if(xAxis.option('Visible')&&xAxis.option('Grid')){this.xGridRule=this._createGridRule(xAxis)}if(yAxis.option('Visible')&&yAxis.option('Grid')){this.yGridRule=this._createGridRule(yAxis)}this.base(layoutInfo);if(chart.focusWindow){this._createFocusWindow(layoutInfo)}var plotFrameVisible;if(chart.compatVersion()<=1){plotFrameVisible=!!(xAxis.option('EndLine')||yAxis.option('EndLine'))}else{plotFrameVisible=def.get(chart.options,'plotFrameVisible',true)}if(plotFrameVisible){this.pvFrameBar=this._createFrame(layoutInfo,axes)}if(xAxis.scaleType!=='discrete'&&xAxis.option('ZeroLine')){this.xZeroLine=this._createZeroLine(xAxis,layoutInfo)}if(yAxis.scaleType!=='discrete'&&yAxis.option('ZeroLine')){this.yZeroLine=this._createZeroLine(yAxis,layoutInfo)}},_createGridRule:function(axis){var scale=axis.scale;if(scale.isNull){return}var isDiscrete=axis.role.grouping.isDiscrete();var axisPanel=this.chart.axesPanels[axis.id];var rootScene=axisPanel._getRootScene();if(!rootScene){return}var margins=this._layoutInfo.gridMargins;var paddings=this._layoutInfo.gridPaddings;var tick_a=axis.orientation==='x'?'left':'bottom';var len_a=this.anchorLength(tick_a);var obeg_a=this.anchorOrtho(tick_a);var oend_a=this.anchorOpposite(obeg_a);var tick_offset=margins[tick_a]+paddings[tick_a];var obeg=margins[obeg_a];var oend=margins[oend_a];var tickScenes=rootScene.leafs().array();var tickCount=tickScenes.length;if(isDiscrete&&tickCount){tickScenes.push(tickScenes[tickCount-1])}var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(tickScene){return v1f.call(this,tickScene.vars.tick.rawValue)}}}var pvGridRule=new pvc.visual.Rule(this,this.pvPanel,{extensionId:axis.extensionPrefixes.map(function(prefix){return prefix+'Grid'}),wrapper:wrapper}).lock('data',tickScenes).lock(len_a,null).override('defaultColor',function(){return pv.color("#f0f0f0")}).pvMark.lineWidth(1).antialias(true)[obeg_a](obeg)[oend_a](oend).zOrder(-12).events('none');if(isDiscrete){var halfStep=scale.range().step/2;pvGridRule.lock(tick_a,function(tickScene){var tickPosition=tick_offset+scale(tickScene.vars.tick.value);var isLastLine=this.index===tickCount;return tickPosition+(isLastLine?halfStep:-halfStep)})}else{pvGridRule.lock(tick_a,function(tickScene){return tick_offset+scale(tickScene.vars.tick.value)})}return pvGridRule},_createFrame:function(layoutInfo,axes){if(axes.base.scale.isNull||(axes.ortho.scale.isNull&&(!axes.ortho2||axes.ortho2.scale.isNull))){return}var margins=layoutInfo.gridMargins;var left=margins.left;var right=margins.right;var top=margins.top;var bottom=margins.bottom;var extensionIds=[];if(this.compatVersion()<=1){extensionIds.push('xAxisEndLine');extensionIds.push('yAxisEndLine')}extensionIds.push('plotFrame');return new pvc.visual.Panel(this,this.pvPanel,{extensionId:extensionIds}).pvMark.lock('left',left).lock('right',right).lock('top',top).lock('bottom',bottom).lock('fillStyle',null).events('none').strokeStyle("#666666").lineWidth(1).antialias(false).zOrder(-8)},_createZeroLine:function(axis,layoutInfo){var scale=axis.scale;if(!scale.isNull){var domain=scale.domain();if(domain[0]*domain[1]<-1e-12){var a=axis.orientation==='x'?'left':'bottom';var len_a=this.anchorLength(a);var obeg_a=this.anchorOrtho(a);var oend_a=this.anchorOpposite(obeg_a);var margins=layoutInfo.gridMargins;var paddings=layoutInfo.gridPaddings;var zeroPosition=margins[a]+paddings[a]+scale(0);var obeg=margins[obeg_a];var oend=margins[oend_a];var rootScene=new pvc.visual.Scene(null,{panel:this});return new pvc.visual.Rule(this,this.pvPanel,{extensionId:axis.extensionPrefixes.map(function(prefix){return prefix+'ZeroLine'})}).lock('data',[rootScene]).lock(len_a,null).lock(obeg_a,obeg).lock(oend_a,oend).lock(a,zeroPosition).override('defaultColor',function(){return pv.color("#666666")}).pvMark.events('none').lineWidth(1).antialias(true).zOrder(-9)}}},_createFocusWindow:function(layoutInfo){var me=this;var topRoot=me.topRoot;var chart=me.chart;var focusWindow=chart.focusWindow.base;var axis=focusWindow.axis;var scale=axis.scale;if(scale.isNull){return}var resizable=focusWindow.option('Resizable');var movable=focusWindow.option('Movable');var isDiscrete=axis.isDiscrete();var isV=chart.isOrientationVertical();var a_left=isV?'left':'top';var a_top=isV?'top':'left';var a_width=me.anchorOrthoLength(a_left);var a_right=me.anchorOpposite(a_left);var a_height=me.anchorOrthoLength(a_top);var a_bottom=me.anchorOpposite(a_top);var a_x=isV?'x':'y';var a_dx='d'+a_x;var a_y=isV?'y':'x';var a_dy='d'+a_y;var margins=layoutInfo.gridMargins;var paddings=layoutInfo.gridPaddings;var space={left:margins.left+paddings.left,right:margins.right+paddings.right,top:margins.top+paddings.top,bottom:margins.bottom+paddings.bottom};space.width=space.left+space.right;space.height=space.top+space.bottom;var clientSize=layoutInfo.clientSize;var wf=clientSize[a_width];var hf=clientSize[a_height];var w=wf-space[a_width];var h=hf-space[a_height];var padLeft=paddings[a_left];var padRight=paddings[a_right];var scene=new pvc.visual.Scene(null,{panel:this});var band=isDiscrete?scale.range().step:0;var halfBand=band/2;scene[a_x]=scale(focusWindow.begin)-halfBand,scene[a_dx]=band+(scale(focusWindow.end)-halfBand)-scene[a_x],resetSceneY();function resetSceneY(){scene[a_y]=0-paddings[a_top];scene[a_dy]=h+paddings[a_top]+paddings[a_bottom]}var sceneProp=function(p){return function(){return scene[p]}};var boundLeft=function(){var begin=scene[a_x];return Math.max(0,Math.min(w,begin))};var boundWidth=function(){var begin=boundLeft();var end=scene[a_x]+scene[a_dx];end=Math.max(0,Math.min(w,end));return end-begin};var addSelBox=function(panel,id){return new pvc.visual.Bar(me,panel,{extensionId:id,normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true,showsInteraction:false}).pvMark.lock('data').lock('visible').lock(a_left,boundLeft).lock(a_width,boundWidth).lock(a_top,sceneProp(a_y)).lock(a_height,sceneProp(a_dy)).lock(a_bottom).lock(a_right).sign};var baseBgPanel=this._plotBgPanel.pvPanel.borderPanel;baseBgPanel.lock('data',[scene]);if(movable&&resizable){baseBgPanel.paddingPanel.lock('events','all').lock('cursor','crosshair').event('mousedown',pv.Behavior.select().autoRender(false).collapse(isV?'y':'x').positionConstraint(function(drag){var op=drag.phase==='start'?'new':'resize-end';return positionConstraint(drag,op)})).event('selectstart',function(ev){resetSceneY();onDrag(ev)}).event('select',onDrag).event('selectend',onDrag)}else{baseBgPanel.paddingPanel.events('all')}var focusBg=addSelBox(baseBgPanel.paddingPanel,'focusWindowBg').override('defaultColor',function(type){return pvc.invisibleFill}).pvMark;if(movable){focusBg.lock('events','all').lock('cursor','move').event("mousedown",pv.Behavior.drag().autoRender(false).collapse(isV?'y':'x').positionConstraint(function(drag){positionConstraint(drag,'move')})).event("drag",onDrag).event("dragend",onDrag)}else{focusBg.events('none')}var baseFgPanel=new pvc.visual.Panel(me,me.pvPanel).pvMark.lock('data',[scene]).lock('visible').lock('fillStyle',pvc.invisibleFill).lock('left',space.left).lock('right',space.right).lock('top',space.top).lock('bottom',space.bottom).lock('zOrder',10).lock('events',function(){var drag=scene.drag;return drag&&drag.phase!=='end'?'all':'none'}).lock('cursor',function(){var drag=scene.drag;return drag&&drag.phase!=='end'?((drag.type==='drag'||(drag.type==='select'&&!resizable))?'move':(isV?'ew-resize':'ns-resize')):null}).antialias(false);var curtainFillColor='rgba(20, 20, 20, 0.1)';new pvc.visual.Bar(me,baseFgPanel,{extensionId:'focusWindowBaseCurtain',normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true,showsInteraction:false}).override('defaultColor',function(type){return type==='stroke'?null:curtainFillColor}).pvMark.lock('data',[scene,scene]).lock('visible').lock('events','none').lock(a_left,function(){return!this.index?-padLeft:boundLeft()+boundWidth()}).lock(a_right,function(){return!this.index?null:-padRight}).lock(a_width,function(){return!this.index?padLeft+boundLeft():null}).lock(a_top,sceneProp(a_y)).lock(a_height,sceneProp(a_dy)).lock(a_bottom);var selectBoxFg=addSelBox(baseFgPanel,'focusWindow').override('defaultColor',function(type){return null}).pvMark.lock('events','none');var addResizeSideGrip=function(side){var a_begin=(side==='left'||side==='top')?'begin':'end';var opposite=me.anchorOpposite(side);var fillColor='linear-gradient(to '+opposite+', '+curtainFillColor+', #444 90%)';var grip=new pvc.visual.Bar(me,selectBoxFg.anchor(side),{extensionId:focusWindow.id+'Grip'+def.firstUpperCase(a_begin),normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true,showsInteraction:false}).override('defaultColor',function(type){return type==='stroke'?null:fillColor}).pvMark.lock('data').lock('visible')[a_top](scene[a_y])[a_height](scene[a_dy]);if(resizable){var opId='resize-'+a_begin;grip.lock('events','all')[a_width](5).cursor(isV?'ew-resize':'ns-resize').event("mousedown",pv.Behavior.resize(side).autoRender(false).positionConstraint(function(drag){positionConstraint(drag,opId)}).preserveOrtho(true)).event("resize",onDrag).event("resizeend",onDrag)}else{grip.events('none')[a_width](1)}return grip};addResizeSideGrip(a_left);addResizeSideGrip(a_right);function onDrag(){var ev=arguments[arguments.length-1];var isEnd=ev.drag.phase==='end';topRoot._isRubberBandSelecting=!isEnd;baseBgPanel.render();baseFgPanel.render();var pbeg=scene[a_x];var pend=scene[a_x]+scene[a_dx];if(!isV){var temp=w-pbeg;pbeg=w-pend;pend=temp}focusWindow._updatePosition(pbeg,pend,isEnd,true)}var a_p=a_x;var a_dp=a_dx;function positionConstraint(drag,op){var m=drag.m;var p=m[a_p];var b,e,l;var l0=scene[a_dp];var target;switch(op){case'new':l=0;target='begin';break;case'resize-begin':l=l0;target='begin';break;case'move':l=l0;target='begin';break;case'resize-end':l=p-scene[a_p];target='end';break}var min=drag.min[a_p];var max=drag.max[a_p];var oper={type:op,target:target,point:p,length:l,length0:l0,min:min,max:max,minView:0,maxView:w};focusWindow._constraintPosition(oper);m[a_p]=oper.point;switch(op){case'resize-begin':oper.max=Math.min(oper.max,scene[a_p]+scene[a_dp]);break;case'resize-end':oper.min=Math.max(oper.min,scene[a_p]);break}drag.min[a_p]=oper.min;drag.max[a_p]=oper.max}},_getOrthoAxis:function(type){var orthoType=type==='base'?'ortho':'base';return this.chart.axes[orthoType]},_getDatumsOnRect:function(datumMap,rect,keyArgs){var chart=this.chart,xAxisPanel=chart.axesPanels.x,yAxisPanel=chart.axesPanels.y,xDatumMap,yDatumMap;if(xAxisPanel){xDatumMap=new def.Map();xAxisPanel._getDatumsOnRect(xDatumMap,rect,keyArgs);if(!xDatumMap.count){xDatumMap=null}}if(yAxisPanel){yDatumMap=new def.Map();yAxisPanel._getOwnDatumsOnRect(yDatumMap,rect,keyArgs);if(!yDatumMap.count){yDatumMap=null}}if(xDatumMap&&yDatumMap){xDatumMap.intersect(yDatumMap,datumMap);keyArgs.toggle=true}else if(xDatumMap){datumMap.copy(xDatumMap)}else if(yDatumMap){datumMap.copy(yDatumMap)}else{chart.plotPanelList.forEach(function(plotPanel){plotPanel._getDatumsOnRect(datumMap,rect,keyArgs)},this)}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcCategoricalAbstract.js b/pacotes/ccc2/compacto/pvcCategoricalAbstract.js deleted file mode 100755 index f8c9fe0..0000000 --- a/pacotes/ccc2/compacto/pvcCategoricalAbstract.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.CategoricalAbstract',pvc.CartesianAbstract).init(function(options){this.base(options);var parent=this.parent;if(parent){this._catRole=parent._catRole}}).add({_initVisualRoles:function(){this.base();this._catRole=this._addVisualRole('category',this._getCategoryRoleSpec())},_getCategoryRoleSpec:function(){return{isRequired:true,defaultDimension:'category*',autoCreateDimension:true}},_generateTrendsDataCellCore:function(newDatums,dataCell,trendInfo){var serRole=this._serRole;var xRole=this._catRole;var yRole=dataCell.role;var trendOptions=dataCell.trend;this._warnSingleContinuousValueRole(yRole);var dataPartDimName=this._dataPartRole.firstDimensionName();var yDimName=yRole.firstDimensionName();var xDimName;var isXDiscrete=xRole.isDiscrete();if(!isXDiscrete){xDimName=xRole.firstDimensionName()}var sumKeyArgs={zeroIfNone:false};var ignoreNullsKeyArgs={ignoreNulls:false};var data=this.visibleData(dataCell.dataPartValue);var allPartsData=this.visibleData(null,ignoreNullsKeyArgs);var allCatDataRoot=allPartsData.flattenBy(xRole,ignoreNullsKeyArgs);var allCatDatas=allCatDataRoot._children;def.scope(function(){return(serRole&&serRole.isBound())?data.flattenBy(serRole).children():def.query([null])}).each(genSeriesTrend,this);function genSeriesTrend(serData1){var funX=isXDiscrete?null:function(allCatData){return allCatData.atoms[xDimName].value};var funY=function(allCatData){var group=data._childrenByKey[allCatData.key];if(group&&serData1){group=group._childrenByKey[serData1.key]}return group?group.dimensions(yDimName).sum(sumKeyArgs):null};var options=def.create(trendOptions,{rows:def.query(allCatDatas),x:funX,y:funY});var trendModel=trendInfo.model(options);var dataPartAtom=data.owner.dimensions(dataPartDimName).intern(this.root._firstTrendAtomProto);if(trendModel){allCatDatas.forEach(function(allCatData,index){var trendX=isXDiscrete?index:allCatData.atoms[xDimName].value;var trendY=trendModel.sample(trendX,funY(allCatData),index);if(trendY!=null){var catData=data._childrenByKey[allCatData.key];var efCatData=catData||allCatData;var atoms;if(serData1){var catSerData=catData&&catData._childrenByKey[serData1.key];if(catSerData){atoms=Object.create(catSerData._datums[0].atoms)}else{atoms=Object.create(efCatData._datums[0].atoms);def.copyOwn(atoms,serData1.atoms)}}else{atoms=Object.create(efCatData._datums[0].atoms)}atoms[yDimName]=trendY;atoms[dataPartDimName]=dataPartAtom;var newDatum=new pvc.data.Datum(efCatData.owner,atoms);newDatum.isVirtual=true;newDatum.isTrend=true;newDatum.trendType=trendInfo.type;newDatums.push(newDatum)}},this)}}},_interpolateDataCell:function(dataCell){var nullInterpMode=dataCell.nullInterpolationMode;if(nullInterpMode){var InterpType;switch(dataCell.nullInterpolationMode){case'linear':InterpType=pvc.data.LinearInterpolationOper;break;case'zero':InterpType=pvc.data.ZeroInterpolationOper;break;case'none':break;default:throw def.error.argumentInvalid('nullInterpolationMode',''+nullInterpMode)}if(InterpType){this._warnSingleContinuousValueRole(dataCell.role);var visibleData=this.visibleData(dataCell.dataPartValue);if(visibleData.childCount()>0){var allPartsData=this.visibleData(null,{ignoreNulls:false});new InterpType(allPartsData,visibleData,this._catRole,this._serRole,dataCell.role,true).interpolate()}}}},_createVisibleData:function(dataPartValue,keyArgs){var serGrouping=this._serRole&&this._serRole.flattenedGrouping();var catGrouping=this._catRole.flattenedGrouping();var partData=this.partData(dataPartValue);var ignoreNulls=def.get(keyArgs,'ignoreNulls');var groupKeyArgs={visible:true,isNull:ignoreNulls?false:null};return serGrouping?partData.groupBy([catGrouping,serGrouping],groupKeyArgs):partData.groupBy(catGrouping,groupKeyArgs)},_getContinuousVisibleCellExtent:function(valueAxis,valueDataCell){var valueRole=valueDataCell.role;switch(valueRole.name){case'series':case'category':return this.base(valueAxis,valueDataCell)}this._warnSingleContinuousValueRole(valueRole);var dataPartValue=valueDataCell.dataPartValue;var valueDimName=valueRole.firstDimensionName();var data=this.visibleData(dataPartValue);var useAbs=valueAxis.scaleUsesAbs();if(valueAxis.type!=='ortho'||!valueDataCell.isStacked){return data.leafs().select(function(serGroup){var value=serGroup.dimensions(valueDimName).sum();return useAbs&&value<0?-value:value}).range()}return data.children().select(function(catGroup){var range=this._getStackedCategoryValueExtent(catGroup,valueDimName,useAbs);if(range){return{range:range,group:catGroup}}},this).where(def.notNully).reduce(function(result,rangeInfo){return this._reduceStackedCategoryValueExtent(result,rangeInfo.range,rangeInfo.group)}.bind(this),null)},_getStackedCategoryValueExtent:function(catGroup,valueDimName,useAbs){var posSum=null,negSum=null;catGroup.children().select(function(serGroup){var value=serGroup.dimensions(valueDimName).sum();return useAbs&&value<0?-value:value}).each(function(value){if(value!=null){if(value>=0){posSum+=value}else{negSum+=value}}});if(posSum==null&&negSum==null){return null}return{max:posSum||0,min:negSum||0}},_reduceStackedCategoryValueExtent:function(result,catRange,catGroup){return pvc.unionExtents(result,catRange)},_coordinateSmallChartsLayout:function(scopesByType){this.base(scopesByType);var titleSizeMax=0;var titleOrthoLen;var axisIds=null;var sizesMaxByAxisId={};this.children.forEach(function(childChart){childChart.basePanel.layout();var size;var panel=childChart.titlePanel;if(panel){if(!titleOrthoLen){titleOrthoLen=panel.anchorOrthoLength()}size=panel[titleOrthoLen];if(size>titleSizeMax){titleSizeMax=size}}var axesPanels=childChart.axesPanels;if(!axisIds){axisIds=def.query(def.ownKeys(axesPanels)).where(function(alias){return alias===axesPanels[alias].axis.id}).select(function(id){sizesMaxByAxisId[id]={axis:0,title:0};return id}).array()}axisIds.forEach(function(id){var axisPanel=axesPanels[id];var sizes=sizesMaxByAxisId[id];var ol=axisPanel.axis.orientation==='x'?'height':'width';size=axisPanel[ol];if(size>sizes.axis){sizes.axis=size}var titlePanel=axisPanel.titlePanel;if(titlePanel){size=titlePanel[ol];if(size>sizes.title){sizes.title=size}}})},this);this.children.forEach(function(childChart){if(titleSizeMax>0){var panel=childChart.titlePanel;panel.size=panel.size.clone().set(titleOrthoLen,titleSizeMax)}var axesPanels=childChart.axesPanels;axisIds.forEach(function(id){var axisPanel=axesPanels[id];var sizes=sizesMaxByAxisId[id];var ol=axisPanel.axis.orientation==='x'?'height':'width';axisPanel.size=axisPanel.size.clone().set(ol,sizes.axis);var titlePanel=axisPanel.titlePanel;if(titlePanel){titlePanel.size=titlePanel.size.clone().set(ol,sizes.title)}});childChart.basePanel.invalidateLayout()},this)},defaults:{orthoAxisOrdinal:false}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcCategoricalAbstractPanel.js b/pacotes/ccc2/compacto/pvcCategoricalAbstractPanel.js deleted file mode 100755 index e87ad1a..0000000 --- a/pacotes/ccc2/compacto/pvcCategoricalAbstractPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.CategoricalAbstractPanel',pvc.CartesianAbstractPanel).init(function(chart,parent,plot,options){this.base(chart,parent,plot,options);this.stacked=plot.option('Stacked')}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcDataTree.js b/pacotes/ccc2/compacto/pvcDataTree.js deleted file mode 100755 index ad015eb..0000000 --- a/pacotes/ccc2/compacto/pvcDataTree.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.DataTree',pvc.BaseChart).init(function(options){options=options||{};options.dimensionGroups=options.dimensionGroups||{};if(!options.dimensionGroups.value){options.dimensionGroups.value={valueType:null}}this.base(options)}).add({structEngine:null,structMetadata:null,structDataset:null,DataTreePanel:null,_getColorRoleSpec:function(){return{isRequired:true,defaultSourceRole:'category',requireIsDiscrete:true}},setStructData:function(data){this.structDataset=data.resultset;if(!this.structDataset.length){this._log("Warning: Structure-dataset is empty")}this.structMetadata=data.metadata;if(!this.structMetadata.length){this._log("Warning: Structure-Metadata is empty")}},_preRenderContent:function(contentOptions){var structEngine=this.structEngine;var structType=structEngine?structEngine.type:new pvc.data.ComplexType();structType.addDimension('value',{});var translOptions={seriesInRows:true,crosstabMode:true};var translation=new pvc.data.CrosstabTranslationOper(structType,this.structDataset,this.structMetadata,translOptions);translation.configureType();if(!structEngine){structEngine=this.structEngine=new pvc.data.Data({type:structType})}structEngine.load(translation.execute(structEngine));if(pvc.debug>=3){this._log(this.structEngine.getInfo())}this.dataTreePanel=new pvc.DataTreePanel(this,this.basePanel,def.create(contentOptions,{topRuleOffset:this.options.topRuleOffset,botRuleOffset:this.options.botRuleOffset,leftRuleOffset:this.options.leftRuleOffset,rightRuleOffset:this.options.rightRuleOffset,boxplotColor:this.options.boxplotColor,valueFontsize:this.options.valueFontsize,headerFontsize:this.options.headerFontsize,border:this.options.border,perpConnector:this.options.perpConnector,numDigits:this.options.numDigits,minVerticalSpace:this.options.minVerticalSpace,connectorSpace:this.options.connectorSpace,minAspectRatio:this.options.minAspectRatio}))},defaults:{compatVersion:1,topRuleOffset:30,botRuleOffset:30,leftRuleOffset:60,rightRuleOffset:60,boxplotColor:"grey",headerFontsize:16,valueFontsize:20,border:2,perpConnector:false,numDigits:0,connectorSpace:0.15,minVerticalSpace:0.05,minAspectRatio:2.0}});def.type('pvc.DataTreePanel',pvc.PlotPanel).add({pvDataTree:null,treeElements:null,structMap:null,structArr:null,hRules:null,vRules:null,rules:null,generatePerpConnectors:function(leftLength){this.hRules=[];this.vRules=[];this.rules=[];for(var e in this.structMap){var elem=this.structMap[e];if(elem.children!=null){var min=+10000,max=-10000;var theLeft=elem.left+elem.width;this.hRules.push({"left":theLeft,"width":leftLength,"bottom":elem.bottom+elem.height/2});theLeft+=leftLength;for(var i in elem.children){var child=this.structMap[elem.children[i]];var theBottom=child.bottom+child.height/2;if(theBottom>max){max=theBottom}if(theBottommin){this.vRules.push({"left":theLeft,"bottom":min,"height":max-min})}}}},generateLineSegment:function(x1,y1,x2,y2){var line=[];line.push({"x":x1,"y":y1});line.push({"x":x2,"y":y2});this.rules.push(line)},generateConnectors:function(leftLength){this.hRules=[];this.vRules=[];if(this.chart.options.perpConnector){this.generatePerpConnectors(leftLength);return}this.rules=[];for(var e in this.structMap){var elem=this.structMap[e];if(elem.children!=null){var theCenter,child,i;var min=+10000,max=-10000;for(i in elem.children){child=this.structMap[elem.children[i]];theCenter=child.bottom+child.height/2;if(theCenter>max){max=theCenter}if(theCenter4);var e;for(e in this.treeElements){this.treeElements[e]=$.trim(this.treeElements[e])}var bounds=[];bounds.getElement=function(label){if(bounds[label]==null){bounds[label]={"min":+10000,"max":-10000}}return bounds[label]};bounds.addValue=function(label,value){var bnd=bounds.getElement(label);if(valuebnd.max){bnd.max=value}return bnd};var col,colnr,elem,row;for(e in this.treeElements){elem=this.treeElements[e];col=elem[0];colnr=col.charCodeAt(0);row=parseInt(elem.slice(1),10);bounds.addValue("__cols",colnr);bounds.addValue(col,row)}var bnds=bounds.getElement("__cols");var gridWidth=this.innerWidth/(bnds.max-bnds.min+1);var connectorWidth=options.connectorSpace*gridWidth;var cellWidth=gridWidth-connectorWidth;var maxCellHeight=cellWidth/options.minAspectRatio;var colBase=bnds.min;delete bounds.__cols;for(e in bounds){bnds=bounds[e];if(typeof bnds=="function"){continue}var numRows=bnds.max-bnds.min+1;bnds.gridHeight=this.innerHeight/numRows;bnds.cellHeight=bnds.gridHeight*(1.0-options.minVerticalSpace);if(bnds.cellHeight>maxCellHeight){bnds.cellHeight=maxCellHeight}bnds.relBottom=(bnds.gridHeight-bnds.cellHeight)/2;bnds.numRows=numRows}var whitespaceQuote=new RegExp('[\\s\"\']+',"g");this.structMap={};for(e in this.treeElements){var box={};elem=this.treeElements[e];box.box_id=elem;this.structMap[elem]=box;col=elem[0];colnr=col.charCodeAt(0);row=parseInt(elem.slice(1),10);bnds=bounds.getElement(col);box.colIndex=colnr-colBase;box.rowIndex=bnds.numRows-(row-bnds.min)-1;box.left=this.leftOffs+box.colIndex*gridWidth;box.width=cellWidth;if(bottomHeightSpecified){box.bottom=values[4][e];box.height=values[5][e]}else{box.bottom=this.botOffs+box.rowIndex*bnds.gridHeight+bnds.relBottom;box.height=bnds.cellHeight}box.label=values[0][e];box.selector=values[1][e];box.aggregation=values[2][e];var children=(values[3][e]||'').replace(whitespaceQuote," ");box.children=(children===" "||children==="")?null:children.split(" ")}this.generateConnectors((gridWidth-cellWidth)/2);this.structArr=[];for(e in this.structMap){elem=this.structMap[e];this.structArr.push(elem)}},findDataValue:function(key,data){for(var i=0;idat[0]){sp.hScale=pv.Scale.linear(dat[0],dat[4])}else{noBox=true;sp.hScale=pv.Scale.linear(dat[0]-1e-10,dat[0]+1e-10)}sp.hScale.range(elem.left+rlMargin,elem.left+elem.width-rlMargin);var avLabel=""+dat[2];var i;for(i=0;i0)&&(typeof window[selPar]!="undefined")){selPar=window[selPar];this.addDataPoint(selPar)}}},_createCore:function(){var myself=this;var options=this.chart.options;options.smValueFontsize=Math.round(0.6*options.valueFontsize);options.smValueFont=""+options.smValueFontsize+"px sans-serif";options.valueFont=""+options.valueFontsize+"px sans-serif";var topRuleOffs=options.topRuleOffset,botRuleOffs=options.botRuleOffset,leftRuleOffs=options.leftRuleOffset;this.innerWidth=this.width-leftRuleOffs-options.rightRuleOffset;this.innerHeight=this.height-topRuleOffs-botRuleOffs;this.botOffs=botRuleOffs;this.leftOffs=leftRuleOffs;this.retrieveStructure();this.retrieveData();var topMargin=options.headerFontsize+3;var rules=this.rules;var i;for(i=0;i=5;var margins=new pvc.Sides(0);var paddings=new pvc.Sides(0);var remSize=def.copyOwn(layoutInfo.clientSize);var aolMap=pvc.BasePanel.orthogonalLength;var aoMap=pvc.BasePanel.relativeAnchor;var alMap=pvc.BasePanel.parallelLength;var childKeyArgs={force:true,referenceSize:layoutInfo.clientSize};var fillChildren=[];var sideChildren=[];var paddingHistory={};var LoopDetected=1;var NormalPaddingsChanged=2;var OverflowPaddingsChanged=4;var emptyNewPaddings=new pvc.Sides();var isDisasterRecovery=false;if(useLog){me._group("CCC GRID LAYOUT clientSize = "+pvc.stringify(remSize))}try{this._children.forEach(initChild);if(useLog){me._group("Phase 1 - Determine MARGINS and FILL SIZE from SIDE panels")}try{sideChildren.forEach(layoutChild1Side)}finally{if(useLog){me._groupEnd();me._log("Final FILL margins = "+pvc.stringify(margins));me._log("Final FILL border size = "+pvc.stringify(remSize))}}if(useLog){me._group("Phase 2 - Determine COMMON PADDINGS")}try{doMaxTimes(9,layoutCycle)}finally{if(useLog){me._groupEnd();me._log("Final FILL clientSize = "+pvc.stringify({width:(remSize.width-paddings.width),height:(remSize.height-paddings.height)}));me._log("Final COMMON paddings = "+pvc.stringify(paddings))}}layoutInfo.gridMargins=new pvc.Sides(margins);layoutInfo.gridPaddings=new pvc.Sides(paddings);layoutInfo.gridSize=new pvc.Size(remSize)}finally{if(useLog){me._groupEnd()}}function layoutCycle(remTimes,iteration){if(useLog){me._group("LayoutCycle "+(isDisasterRecovery?"- Disaster MODE":("#"+(iteration+1))))}try{var index,count;var canChange=layoutInfo.canChange!==false&&!isDisasterRecovery&&(remTimes>0);var paddingsChanged;var ownPaddingsChanged=false;var breakAndRepeat;index=0;count=sideChildren.length;while(index0){if(useLog){me._log("SIDE Child #"+(index+1)+" changed normal paddings")}breakAndRepeat=true}else if(pvc.debug>=2){me._warn("SIDE Child #"+(index+1)+" changed paddings but no more iterations possible.")}}if((paddingsChanged&LoopDetected)!==0){isDisasterRecovery=true;layoutCycle(0);return false}if(breakAndRepeat){return true}}}finally{if(useLog){me._groupEnd()}}index++}if(ownPaddingsChanged){if(useLog){me._log("Restarting due to overflowPaddings change")}return false}index=0;count=fillChildren.length;while(index0){if(pvc.debug>=5){me._log("FILL Child #"+(index+1)+" increased paddings")}breakAndRepeat=true}else if(pvc.debug>=2){me._warn("FILL Child #"+(index+1)+" increased paddings but no more iterations possible.")}}if((paddingsChanged&LoopDetected)!==0){isDisasterRecovery=true;layoutCycle(0);return false}if(breakAndRepeat){return true}}}finally{if(useLog){me._groupEnd()}}index++}return false}finally{if(useLog){me._groupEnd()}}}function doMaxTimes(maxTimes,fun){var index=0;while(maxTimes--){if(fun(maxTimes,index)===false){return true}index++}return false}function initChild(child){var a=child.anchor;if(a){if(a==='fill'){fillChildren.push(child);var childPaddings=child.paddings.resolve(childKeyArgs.referenceSize);paddings=pvc.Sides.resolvedMax(paddings,childPaddings)}else{def.hasOwn(aoMap,a)||def.fail.operationInvalid("Unknown anchor value '{0}'",[a]);sideChildren.push(child)}}}function layoutChild1Side(child,index){if(useLog){me._group("SIDE Child #"+(index+1))}try{var paddingsChanged=0;var a=child.anchor;childKeyArgs.paddings=filterAnchorPaddings(a,paddings);child.layout(new pvc.Size(remSize),childKeyArgs);if(child.isVisible){paddingsChanged|=checkAnchorPaddingsChanged(a,paddings,child);positionChildNormal(a,child);updateSide(a,child)}return paddingsChanged}finally{if(useLog){me._groupEnd()}}}function layoutChildFill(child,canChange){var paddingsChanged=0;var a=child.anchor;childKeyArgs.paddings=filterAnchorPaddings(a,paddings);childKeyArgs.canChange=canChange;child.layout(new pvc.Size(remSize),childKeyArgs);if(child.isVisible){paddingsChanged|=checkAnchorPaddingsChanged(a,paddings,child,canChange);positionChildNormal(a,child);positionChildOrtho(child,a)}return paddingsChanged}function layoutChild2Side(child,canChange){var paddingsChanged=0;if(child.isVisible){var a=child.anchor;var al=alMap[a];var aol=aolMap[a];var length=remSize[al];var olength=child[aol];var childSize2=new pvc.Size(def.set({},al,length,aol,olength));childKeyArgs.paddings=filterAnchorPaddings(a,paddings);childKeyArgs.canChange=canChange;child.layout(childSize2,childKeyArgs);if(child.isVisible){paddingsChanged=checkAnchorPaddingsChanged(a,paddings,child,canChange)|checkOverflowPaddingsChanged(a,layoutInfo.paddings,child,canChange);if(!paddingsChanged){positionChildOrtho(child,child.align)}}}return paddingsChanged}function positionChildNormal(side,child){var sidePos;if(side==='fill'){side='left';sidePos=margins.left+remSize.width/2-(child.width/2)}else{sidePos=margins[side]}child.setPosition(def.set({},side,sidePos))}function updateSide(side,child){var sideol=aolMap[side],olen=child[sideol];margins[side]+=olen;remSize[sideol]-=olen}function positionChildOrtho(child,align){var sideo;if(align==='fill'){align='middle'}var sideOPos;switch(align){case'top':case'bottom':case'left':case'right':sideo=align;sideOPos=margins[sideo];break;case'middle':sideo='bottom';sideOPos=margins.bottom+(remSize.height/2)-(child.height/2);break;case'center':sideo='left';sideOPos=margins.left+remSize.width/2-(child.width/2);break}child.setPosition(def.set({},sideo,sideOPos))}function filterAnchorPaddings(a,paddings){var filtered=new pvc.Sides();getAnchorPaddingsNames(a).forEach(function(side){filtered.set(side,paddings[side])});return filtered}function checkAnchorPaddingsChanged(a,paddings,child,canChange){var newPaddings=child._layoutInfo.requestPaddings;var changed=0;if(newPaddings){if(useLog&&pvc.debug>=10){me._log("=> clientSize="+pvc.stringify(child._layoutInfo.clientSize));me._log("<= requestPaddings="+pvc.stringify(newPaddings))}getAnchorPaddingsNames(a).forEach(function(side){var value=paddings[side]||0;var newValue=Math.floor(10000*(newPaddings[side]||0))/10000;var increase=newValue-value;var minChange=Math.max(1,Math.abs(0.01*value));if(increase!==0&&Math.abs(increase)>=minChange){if(!canChange){if(pvc.debug>=2){me._warn("CANNOT change but child wanted to: "+side+"="+newValue)}}else{changed|=NormalPaddingsChanged;paddings[side]=newValue;if(useLog){me._log("Changed padding "+side+" <- "+newValue)}}}});if(changed){var paddingKey=pvc.Sides.names.map(function(side){return(paddings[side]||0).toFixed(0)}).join('|');if(def.hasOwn(paddingHistory,paddingKey)){if(pvc.debug>=2){me._warn("LOOP detected!!!!")}changed|=LoopDetected}else{paddingHistory[paddingKey]=true}paddings.width=paddings.left+paddings.right;paddings.height=paddings.top+paddings.bottom}}return changed}function checkOverflowPaddingsChanged(a,ownPaddings,child,canChange){var overflowPaddings=child._layoutInfo.overflowPaddings||emptyNewPaddings;var changed=0;if(useLog&&pvc.debug>=10){me._log("<= overflowPaddings="+pvc.stringify(overflowPaddings))}getAnchorPaddingsNames(a).forEach(function(side){if(overflowPaddings.hasOwnProperty(side)){var value=ownPaddings[side]||0;var newValue=Math.floor(10000*(overflowPaddings[side]||0))/10000;newValue-=margins[side];var increase=newValue-value;var minChange=Math.max(1,Math.abs(0.05*value));if(increase>=minChange){if(!canChange){if(pvc.debug>=2){me._warn("CANNOT change overflow padding but child wanted to: "+side+"="+newValue)}}else{changed|=OverflowPaddingsChanged;ownPaddings[side]=newValue;if(useLog){me._log("changed overflow padding "+side+" <- "+newValue)}}}}});if(changed){ownPaddings.width=ownPaddings.left+ownPaddings.right;ownPaddings.height=ownPaddings.top+ownPaddings.bottom}return changed}function getAnchorPaddingsNames(a){switch(a){case'left':case'right':return pvc.Sides.vnames;case'top':case'bottom':return pvc.Sides.hnames;case'fill':return pvc.Sides.names}}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcHeatGridChart.js b/pacotes/ccc2/compacto/pvcHeatGridChart.js deleted file mode 100755 index b73f64e..0000000 --- a/pacotes/ccc2/compacto/pvcHeatGridChart.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.HeatGridChart',pvc.CategoricalAbstract).add({_allowColorPerCategory:true,_axisCreateIfUnbound:{'color':true},_processOptionsCore:function(options){this.base(options);def.set(options,'orthoAxisOrdinal',true,'legend',false,'panelSizeRatio',1);var colorDimName='value',sizeDimName='value2';if(this.compatVersion()<=1){switch(this.options.colorValIdx){case 0:colorDimName='value';break;case 1:colorDimName='value2';break;default:colorDimName='value'}switch(this.options.sizeValIdx){case 0:sizeDimName='value';break;case 1:sizeDimName='value2';break;default:sizeDimName='value'}}this._colorDimName=colorDimName;this._sizeDimName=sizeDimName},_getCategoryRoleSpec:function(){var catRoleSpec=this.base();catRoleSpec.requireIsDiscrete=true;return catRoleSpec},_getColorRoleSpec:function(){return{isMeasure:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:this._colorDimName}},_initVisualRoles:function(){this.base();this._addVisualRole('size',{isMeasure:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:this._sizeDimName})},_initPlotsCore:function(){new pvc.visual.HeatGridPlot(this)},_collectPlotAxesDataCells:function(plot,dataCellsByAxisTypeThenIndex){this.base(plot,dataCellsByAxisTypeThenIndex);if(plot.type==='heatGrid'&&plot.option('UseShapes')){var sizeRole=this.visualRoles(plot.option('SizeRole'));if(sizeRole.isBound()){var sizeDataCellsByAxisIndex=def.array.lazy(dataCellsByAxisTypeThenIndex,'size');def.array.lazy(sizeDataCellsByAxisIndex,plot.option('SizeAxis')-1).push({plot:plot,role:sizeRole,dataPartValue:plot.option('DataPart')})}}},_setAxesScales:function(hasMultiRole){this.base(hasMultiRole);if(!hasMultiRole||this.parent){var sizeAxis=this.axes.size;if(sizeAxis&&sizeAxis.isBound()){this._createAxisScale(sizeAxis)}}},_createPlotPanels:function(parentPanel,baseOptions){var heatGridPlot=this.plots.heatGrid;this.heatGridChartPanel=new pvc.HeatGridPanel(this,parentPanel,heatGridPlot,Object.create(baseOptions))},defaults:{colorValIdx:0,sizeValIdx:1,measuresIndexes:[2],axisOffset:0,plotFrameVisible:false,colorNormByCategory:true,numSD:2}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcHeatGridPanel.js b/pacotes/ccc2/compacto/pvcHeatGridPanel.js deleted file mode 100755 index 76e7954..0000000 --- a/pacotes/ccc2/compacto/pvcHeatGridPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.HeatGridPanel',pvc.CategoricalAbstractPanel).init(function(chart,parent,plot,options){this.base(chart,parent,plot,options);this.axes.size=chart._getAxis('size',plot.option('SizeAxis')-1);var roles=this.visualRoles;var sizeRoleName=plot.option('SizeRole');roles.size=chart.visualRoles(sizeRoleName);var valueDimName;if(roles.color.isBound()){valueDimName=roles.color.firstDimensionName()}else if(roles.size.isBound()){valueDimName=roles.size.firstDimensionName()}this._valueDimName=valueDimName;this.useShapes=plot.option('UseShapes');this.shape=plot.option('Shape');this.nullShape=plot.option('NullShape')}).add({pvHeatGrid:null,pvHeatGridLabel:null,defaultBorder:1,nullBorder:2,selectedBorder:2,_createCore:function(){this.base();var chart=this.chart;var a_bottom=this.isOrientationVertical()?"bottom":"left";var xScale=this.axes.x.scale;var yScale=this.axes.y.scale;var w=(xScale.max-xScale.min)/xScale.domain().length;var h=(yScale.max-yScale.min)/yScale.domain().length;if(a_bottom!=="bottom"){var tmp=w;w=h;h=tmp}this._cellWidth=w;this._cellHeight=h;var keyArgs={visible:true},rowRootData=chart.data.flattenBy(chart._serRole,keyArgs),data=this.visibleData(),rootScene=this._buildScene(data,rowRootData),hasColor=rootScene.hasColorRole,hasSize=rootScene.hasSizeRole;var getFillColor;var colorAxis=this.axes.color;var colorNull=colorAxis.option('Missing');if(hasColor){var fillColorScaleByColKey=colorAxis.scalesByCateg;if(fillColorScaleByColKey){getFillColor=function(leafScene){var colorValue=leafScene.vars.color.value;if(colorValue==null){return colorNull}var colAbsKey=leafScene.group.parent.absKey;return fillColorScaleByColKey[colAbsKey](colorValue)}}else{var colorScale=colorAxis.scale;getFillColor=function(leafScene){return colorScale(leafScene.vars.color.value)}}}else{getFillColor=def.fun.constant(colorNull)}var a_left=pvc.BasePanel.relativeAnchor[a_bottom];var a_width=pvc.BasePanel.parallelLength[a_bottom];var a_height=pvc.BasePanel.orthogonalLength[a_bottom];var pvRowPanel=new pvc.visual.Panel(this,this.pvPanel).pvMark.data(rootScene.childNodes)[a_bottom](function(){return this.index*h})[a_height](h);var wrapper;if(this.compatVersion()<=1){var colorValuesBySerAndCat=def.query(rootScene.childNodes).object({name:function(serScene){return''+serScene.vars.series.value},value:function(serScene){return def.query(serScene.childNodes).object({name:function(leafScene){return''+leafScene.vars.category.value},value:function(leafScene){var colorVar=leafScene.vars.color;return colorVar?(''+colorVar.value):null}})}});wrapper=function(v1f){return function(leafScene){var colorValuesByCat=colorValuesBySerAndCat[leafScene.vars.series.value];var cat=leafScene.vars.category.rawValue;var wrapperParent=Object.create(this.parent);var wrapper=Object.create(this);wrapper.parent=wrapperParent;var catIndex=leafScene.childIndex();var serIndex=leafScene.parent.childIndex();wrapperParent.index=catIndex;wrapper.index=serIndex;return v1f.call(wrapper,colorValuesByCat,cat)}}}var extensionIds=['panel'];if(this.compatVersion()<=1){extensionIds.push('')}keyArgs={extensionId:extensionIds,wrapper:wrapper};if(!this.useShapes){keyArgs.noSelect=keyArgs.noHover=keyArgs.noClick=keyArgs.noDoubleClick=keyArgs.freeColor=false;keyArgs.noTooltip=!!wrapper}var pvHeatGrid=this.pvHeatGrid=new pvc.visual.Panel(this,pvRowPanel,keyArgs).lock('data',function(serScene){return serScene.childNodes}).pvMark.localProperty('colorValue').lock('colorValue',function(leafScene){return leafScene.vars.color.value}).localProperty('sizeValue').lock('sizeValue',function(leafScene){return leafScene.vars.size.value}).lock(a_left,function(){return this.index*w}).lock(a_width,w).antialias(false);if(this.useShapes){this.shapes=this.createHeatMap(w,h,getFillColor,wrapper,hasColor,hasSize)}else{this.shapes=pvHeatGrid.sign.override('defaultColor',function(type){if(type==='stroke'){return null}return getFillColor.call(this.pvMark,this.scene)}).override('interactiveColor',function(color,type){var scene=this.scene;if(scene.isActive){return color.alpha(0.6)}if(scene.anySelected()&&!scene.isSelected()){return this.dimColor(color,type)}return this.base(color,type)}).override('dimColor',function(color){return pvc.toGrayScale(color,0.6)}).pvMark.lineWidth(1.5)}if(this.valuesVisible&&this._valueDimName){var valueDimName=this._valueDimName;this.pvHeatGridLabel=new pvc.visual.Label(this,this.pvHeatGrid.anchor("center"),{extensionId:'label',wrapper:wrapper}).pvMark.font(this.valuesFont).text(function(leafScene){return leafScene.atoms[valueDimName].label})}},_calcDotAreaRange:function(w,h){var maxRadius=Math.min(w,h)/2;if(this.shape==='diamond'){maxRadius/=Math.SQRT2}maxRadius-=2;var maxArea=maxRadius*maxRadius,minArea=12,areaSpan=maxArea-minArea;if(areaSpan<=1){maxArea=Math.max(maxArea,2);minArea=1;areaSpan=maxArea-minArea;if(pvc.debug>=2){this._log("Using rescue mode dot area calculation due to insufficient space.")}}return{min:minArea,max:maxArea,span:areaSpan}},createHeatMap:function(w,h,getFillColor,wrapper,hasColor,hasSize){var me=this,chart=me.chart,nullShapeType=me.nullShape,shapeType=me.shape;var areaRange=me._calcDotAreaRange(w,h);var maxArea=areaRange.max;var sizeScale;if(hasSize){sizeScale=me.axes.size.setScaleRange(areaRange).scale}var notNullSelectedBorder=(me.selectedBorder==null||(+me.selectedBorder)===0)?me.defaultBorder:me.selectedBorder;var nullSelectedBorder=(me.selectedBorder==null||(+me.selectedBorder)===0)?me.nullBorder:me.selectedBorder;var nullDeselectedBorder=me.defaultBorder>0?me.defaultBorder:me.nullBorder;var getShapeSize,getShapeType;if(!hasSize){getShapeType=def.fun.constant(shapeType);getShapeSize=function(){return(hasColor&&!nullShapeType&&this.parent.colorValue()==null)?0:maxArea}}else{getShapeType=function(){return this.parent.sizeValue()!=null?shapeType:nullShapeType};getShapeSize=function(){var sizeValue=this.parent.sizeValue();return(sizeValue==null&&!nullShapeType)?0:sizeScale(sizeValue)}}var keyArgs={extensionId:'dot',freePosition:true,activeSeriesAware:false,noHover:false,wrapper:wrapper};var options=chart.options;if(wrapper&&chart._tooltipEnabled){var customTooltip=options.customTooltip;if(!customTooltip){customTooltip=function(s,c,d){if(d!=null&&d[0]!==undefined){return d.join(', ')}return d}}keyArgs.tooltipArgs={buildTooltip:options.isMultiValued?function(context){var group=context.scene.group;var s=pvc.data.Complex.values(group,chart._serRole.grouping.dimensionNames());var c=pvc.data.Complex.values(group,chart._catRole.grouping.dimensionNames());var d=[];if(hasSize){d[options.sizeValIdx||0]=context.scene.vars.size.value}if(hasColor){d[options.colorValIdx||0]=context.scene.vars.color.value}return customTooltip.call(options,s,c,d)}:function(context){var s=context.scene.vars.series.rawValue;var c=context.scene.vars.category.rawValue;var valueVar=context.scene.vars[hasColor?'color':'size'];var d=valueVar?valueVar.value:null;return customTooltip.call(options,s,c,d)}}}return new pvc.visual.Dot(me,me.pvHeatGrid,keyArgs).override('defaultSize',function(){return getShapeSize.call(this.pvMark,this.scene)}).override('interactiveSize',function(size){if(this.scene.isActive){return Math.max(size,5)*1.5}return size}).override('baseColor',function(){return getFillColor.call(this.pvMark.parent,this.scene)}).override('normalColor',function(color,type){if(type==='stroke'){return color.darker()}return this.base(color,type)}).override('interactiveColor',function(color,type){var scene=this.scene;if(type==='stroke'){if(scene.anySelected()&&!scene.isSelected()){return color}return color.darker()}if(scene.isActive){return color.alpha(0.6)}return this.base(color,type)}).override('dimColor',function(color){return pvc.toGrayScale(color,0.6)}).pvMark.shape(getShapeType).lock('shapeAngle').lineWidth(function(leafScene){if(!hasSize||!me._isNullShapeLineOnly()||this.parent.sizeValue()!=null){return leafScene.isSelected()?notNullSelectedBorder:me.defaultBorder}return leafScene.isSelected()?nullSelectedBorder:nullDeselectedBorder})},_isNullShapeLineOnly:function(){return this.nullShape=='cross'},_getSelectableMarks:function(){return[this.shapes]},renderInteractive:function(){this.pvPanel.render()},_buildScene:function(data,seriesRootData){var me=this;var rootScene=new pvc.visual.Scene(null,{panel:me,group:data});var categDatas=data._children;var roles=me.visualRoles;var colorVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.color);var sizeVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.size);rootScene.hasColorRole=colorVarHelper.isBound();rootScene.hasSizeRole=sizeVarHelper.isBound();seriesRootData.children().each(createSeriesScene);return rootScene;function createSeriesScene(serData1){var serScene=new pvc.visual.Scene(rootScene,{group:serData1});serScene.vars.series=pvc.visual.ValueLabelVar.fromComplex(serData1);categDatas.forEach(function(catData1){createSeriesCategoryScene.call(me,serScene,catData1,serData1)})}function createSeriesCategoryScene(serScene,catData1,serData1){var group=data._childrenByKey[catData1.key]._childrenByKey[serData1.key];var serCatScene=new pvc.visual.Scene(serScene,{group:group});serCatScene.vars.category=pvc.visual.ValueLabelVar.fromComplex(catData1);colorVarHelper.onNewScene(serCatScene,true);sizeVarHelper.onNewScene(serCatScene,true)}}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcLegendPanel.js b/pacotes/ccc2/compacto/pvcLegendPanel.js deleted file mode 100755 index 7fe3e9b..0000000 --- a/pacotes/ccc2/compacto/pvcLegendPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.LegendPanel',pvc.BasePanel).add({pvRule:null,pvDot:null,pvLabel:null,anchor:'bottom',pvLegendPanel:null,textMargin:6,itemPadding:2.5,markerSize:15,font:'10px sans-serif',_calcLayout:function(layoutInfo){return this._getBulletRootScene().layout(layoutInfo)},_createCore:function(layoutInfo){var clientSize=layoutInfo.clientSize,rootScene=this._getBulletRootScene(),itemPadding=rootScene.vars.itemPadding,contentSize=rootScene.vars.size;var isHorizontal=this.isAnchorTopOrBottom();var a_top=isHorizontal?'top':'left';var a_bottom=this.anchorOpposite(a_top);var a_width=this.anchorLength(a_top);var a_height=this.anchorOrthoLength(a_top);var a_center=isHorizontal?'center':'middle';var a_left=isHorizontal?'left':'top';var a_right=this.anchorOpposite(a_left);var leftOffset=0;switch(this.align){case a_right:leftOffset=clientSize[a_width]-contentSize.width;break;case a_center:leftOffset=(clientSize[a_width]-contentSize.width)/2;break}this.pvPanel.overflow("hidden");var pvLegendRowPanel=this.pvPanel.add(pv.Panel).data(rootScene.vars.rows)[a_left](leftOffset)[a_top](function(){var prevRow=this.sibling();return prevRow?(prevRow[a_top]+prevRow[a_height]+itemPadding[a_height]):0})[a_width](function(row){return row.size.width})[a_height](function(row){return row.size.height});var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(itemScene){return v1f.call(this,itemScene.vars.value.rawValue)}}}this.pvLegendPanel=new pvc.visual.Panel(this,pvLegendRowPanel,{extensionId:'panel',wrapper:wrapper,noSelect:false,noClickSelect:true}).lockMark('data',function(row){return row.items}).lock(a_right,null).lock(a_bottom,null).lockMark(a_left,function(clientScene){var itemPadding=clientScene.vars.itemPadding;var prevItem=this.sibling();return prevItem?(prevItem[a_left]+prevItem[a_width]+itemPadding[a_width]):0}).lockMark('height',function(itemScene){return itemScene.vars.clientSize.height}).lockMark(a_top,isHorizontal?function(itemScene){var vars=itemScene.vars;return vars.row.size.height/2-vars.clientSize.height/2}:0).lockMark('width',isHorizontal?function(itemScene){return itemScene.vars.clientSize.width}:function(){return this.parent.width()}).pvMark.def("hidden","false").fillStyle(function(){return this.hidden()=="true"?"rgba(200,200,200,1)":"rgba(200,200,200,0.0001)"}).cursor(function(itemScene){return itemScene.isClickable()?"pointer":null}).event("click",function(itemScene){if(itemScene.isClickable()){return itemScene.click()}});var pvLegendMarkerPanel=new pvc.visual.Panel(this,this.pvLegendPanel).pvMark.left(0).top(0).right(null).bottom(null).width(function(itemScene){return itemScene.vars.markerSize}).height(function(itemScene){return itemScene.vars.clientSize.height});if(pvc.debug>=20){pvLegendRowPanel.strokeStyle('red');this.pvLegendPanel.strokeStyle('green');pvLegendMarkerPanel.strokeStyle('blue')}rootScene.childNodes.forEach(function(groupScene){var pvGroupPanel=new pvc.visual.Panel(this,pvLegendMarkerPanel).pvMark.visible(function(itemScene){return itemScene.parent===groupScene});groupScene.renderer().create(this,pvGroupPanel,groupScene.extensionPrefix,wrapper)},this);this.pvLabel=new pvc.visual.Label(this,pvLegendMarkerPanel.anchor("right"),{extensionId:'label',wrapper:wrapper}).intercept('textStyle',function(itemScene){var baseTextStyle=this.delegateExtension()||"black";return itemScene.isOn()?baseTextStyle:pvc.toGrayScale(baseTextStyle,null,undefined,150)}).pvMark.textAlign('left').text(function(itemScene){return itemScene.vars.value.label}).lock('textMargin',function(itemScene){return itemScene.vars.textMargin-4}).font(function(itemScene){return itemScene.vars.font}).textDecoration(function(itemScene){return itemScene.isOn()?"":"line-through"})},_getExtensionId:function(){return'area'},_getExtensionPrefix:function(){return'legend'},_getSelectableMarks:function(){return[this.pvLegendPanel]},_getBulletRootScene:function(){var rootScene=this._rootScene;if(!rootScene){rootScene=new pvc.visual.legend.BulletRootScene(null,{panel:this,group:this.chart.data,horizontal:this.isAnchorTopOrBottom(),font:this.font,markerSize:this.markerSize,textMargin:this.textMargin,itemPadding:this.itemPadding});this._rootScene=rootScene}return rootScene}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcMetricPoint.js b/pacotes/ccc2/compacto/pvcMetricPoint.js deleted file mode 100755 index 5f9f665..0000000 --- a/pacotes/ccc2/compacto/pvcMetricPoint.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.MetricPointAbstract',pvc.MetricXYAbstract).init(function(options){this.base(options);var parent=this.parent;if(parent){this._colorRole=parent._colorRole;this._sizeRole=parent._sizeRole}}).add({_initPlotsCore:function(){var pointPlot=this._createPointPlot();var trend=pointPlot.option('Trend');if(trend){new pvc.visual.MetricPointPlot(this,{name:'trend',fixed:{DataPart:'trend',TrendType:'none',NullInterpolatioMode:'none',ColorRole:'series',SizeRole:null,SizeAxis:null,OrthoAxis:1},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:false}})}},_hasDataPartRole:function(){return true},_getColorRoleSpec:function(){return{defaultSourceRole:'series',defaultDimension:'color*',dimensionDefaults:{valueType:Number}}},_initVisualRoles:function(){this.base();this._sizeRole=this._addVisualRole('size',{isMeasure:true,requireSingleDimension:true,requireIsDiscrete:false,defaultDimension:'size',dimensionDefaults:{valueType:Number}})},_getTranslationClass:function(translOptions){return def.type(this.base(translOptions)).add(pvc.data.MetricPointChartTranslationOper)},_initData:function(keyArgs){this.base(keyArgs);var sizeGrouping=this._sizeRole.grouping;if(sizeGrouping){this._sizeDim=this.data.dimensions(sizeGrouping.firstDimensionName())}},_collectPlotAxesDataCells:function(plot,dataCellsByAxisTypeThenIndex){this.base(plot,dataCellsByAxisTypeThenIndex);if(plot.type==='scatter'&&plot.option('DotsVisible')){var sizeRoleName=plot.option('SizeRole');if(sizeRoleName){var sizeRole=this.visualRoles(sizeRoleName);if(sizeRole.isBound()){var sizeDataCellsByAxisIndex=def.array.lazy(dataCellsByAxisTypeThenIndex,'size');def.array.lazy(sizeDataCellsByAxisIndex,plot.option('SizeAxis')-1).push({plot:plot,role:this.visualRoles(plot.option('SizeRole')),dataPartValue:plot.option('DataPart')})}}}},_setAxesScales:function(hasMultiRole){this.base(hasMultiRole);if(!hasMultiRole||this.parent){var sizeAxis=this.axes.size;if(sizeAxis&&sizeAxis.isBound()){this._createAxisScale(sizeAxis)}}},_createPlotPanels:function(parentPanel,baseOptions){var options=this.options;var panelOptions=def.set(Object.create(baseOptions),'sizeAxisRatio',options.sizeAxisRatio,'sizeAxisRatioTo',options.sizeAxisRatioTo,'autoPaddingByDotSize',options.autoPaddingByDotSize);var scatterPlot=this.plots.scatter;this.scatterChartPanel=new pvc.MetricPointPanel(this,parentPanel,scatterPlot,panelOptions);var trendPlot=this.plots.trend;if(trendPlot){new pvc.MetricPointPanel(this,parentPanel,trendPlot,Object.create(panelOptions))}},defaults:{axisOriginIsZero:false,tooltipOffset:10}});def.type('pvc.MetricDotChart',pvc.MetricPointAbstract).add({_createPointPlot:function(){return new pvc.visual.MetricPointPlot(this,{fixed:{DotsVisible:true}})}});def.type('pvc.MetricLineChart',pvc.MetricPointAbstract).add({_createPointPlot:function(){return new pvc.visual.MetricPointPlot(this,{fixed:{LinesVisible:true}})}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcMetricPointPanel.js b/pacotes/ccc2/compacto/pvcMetricPointPanel.js deleted file mode 100755 index c346742..0000000 --- a/pacotes/ccc2/compacto/pvcMetricPointPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.MetricPointPanel',pvc.CartesianAbstractPanel).init(function(chart,parent,plot,options){this.base(chart,parent,plot,options);this.axes.size=chart._getAxis('size',(plot.option('SizeAxis')||0)-1);var sizeRoleName=plot.option('SizeRole');this.visualRoles.size=chart.visualRoles(sizeRoleName);this.linesVisible=plot.option('LinesVisible');this.dotsVisible=plot.option('DotsVisible');if(!this.linesVisible&&!this.dotsVisible){this.linesVisible=true;plot.option.specify({'LinesVisible':true})}this.dotShape=plot.option('Shape');if(!this.offsetPaddings){this.offsetPaddings=new pvc.Sides(0.01)}}).add({pvLine:null,pvDot:null,pvLabel:null,pvScatterPanel:null,dotShape:"circle",sizeAxisRatio:1/5,sizeAxisRatioTo:'minWidthHeight',autoPaddingByDotSize:true,_v1DimRoleName:{'category':'x','value':'y'},_creating:function(){var groupScene=this.defaultVisibleBulletGroupScene();if(groupScene&&!groupScene.hasRenderer()){var colorAxis=groupScene.colorAxis;var drawMarker=def.nullyTo(colorAxis.option('LegendDrawMarker',true),this.dotsVisible);var drawRule=def.nullyTo(colorAxis.option('LegendDrawLine',true),this.linesVisible);if(drawMarker||drawRule){var keyArgs={};if((keyArgs.drawMarker=drawMarker)){keyArgs.markerShape=colorAxis.option('LegendShape',true)||'circle';keyArgs.markerPvProto=new pv.Dot().lineWidth(1.5,pvc.extensionTag).shapeSize(12,pvc.extensionTag);this.extend(keyArgs.markerPvProto,'dot',{constOnly:true})}if((keyArgs.drawRule=drawRule)){keyArgs.rulePvProto=new pv.Line().lineWidth(1.5,pvc.extensionTag);this.extend(keyArgs.rulePvProto,'line',{constOnly:true})}groupScene.renderer(new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs))}}},_getRootScene:function(){var me=this;var rootScene=me._rootScene;if(!rootScene){var roles=me.visualRoles;var hasColorRole=roles.color.isBound()&&!me.axes.color.scale.isNull;var hasSizeRole=roles.size.isBound()&&!me.axes.size.scale.isNull;me._rootScene=rootScene=me._buildScene(hasColorRole,hasSizeRole)}return rootScene},_calcLayout:function(layoutInfo){var rootScene=this._getRootScene();if(rootScene.hasSizeRole){var areaRange=this._calcDotAreaRange(layoutInfo);this.sizeScale=this.axes.size.setScaleRange(areaRange).scale}this._calcAxesPadding(layoutInfo,rootScene)},_getDotDiameterRefLength:function(layoutInfo){var clientSize=layoutInfo.clientSize;var paddings=layoutInfo.paddings;switch(this.sizeAxisRatioTo){case'minWidthHeight':return Math.min(clientSize.width+paddings.width,clientSize.height+paddings.height);case'width':return clientSize.width+paddings.width;case'height':return clientSize.height+paddings.height}if(pvc.debug>=2){this._log(def.format("Invalid option 'sizeAxisRatioTo' value. Assuming 'minWidthHeight'.",[this.sizeAxisRatioTo]))}this.sizeRatioTo='minWidthHeight';return this._getDotDiameterRefLength(layoutInfo)},_calcDotRadiusRange:function(layoutInfo){var refLength=this._getDotDiameterRefLength(layoutInfo);var max=(this.sizeAxisRatio/2)*refLength;var min=Math.sqrt(12);return{min:min,max:max}},_calcDotAreaRange:function(layoutInfo){var radiusRange=this._calcDotRadiusRange(layoutInfo);if(this.dotShape==='diamond'){radiusRange.max/=Math.SQRT2;radiusRange.min/=Math.SQRT2}var maxArea=radiusRange.max*radiusRange.max,minArea=radiusRange.min*radiusRange.min,areaSpan=maxArea-minArea;if(areaSpan<=1){maxArea=Math.max(maxArea,2);minArea=1;areaSpan=maxArea-minArea;radiusRange={min:Math.sqrt(minArea),max:Math.sqrt(maxArea)};if(pvc.debug>=3){this._log("Using rescue mode dot area calculation due to insufficient space.")}}return{min:minArea,max:maxArea,span:areaSpan}},_calcAxesPadding:function(layoutInfo,rootScene){var requestPaddings;if(!this.autoPaddingByDotSize){requestPaddings=this._calcRequestPaddings(layoutInfo)}else{var axes=this.axes;var clientSize=layoutInfo.clientSize;var paddings=layoutInfo.paddings;requestPaddings={};axes.x.setScaleRange(clientSize.width);axes.y.setScaleRange(clientSize.height);var sceneXScale=axes.base.sceneScale({sceneVarName:'x'});var sceneYScale=axes.ortho.sceneScale({sceneVarName:'y'});var xLength=axes.base.scale.max;var yLength=axes.ortho.scale.max;var hasSizeRole=rootScene.hasSizeRole;var sizeScale=this.sizeScale;if(!hasSizeRole){var defaultSize=def.number.as(this._getExtension('dot','shapeRadius'),0);if(defaultSize<=0){defaultSize=def.number.as(this._getExtension('dot','shapeSize'),0);if(defaultSize<=0){defaultSize=12}}else{defaultSize=defaultSize*defaultSize}sizeScale=def.fun.constant(defaultSize)}requestPaddings={};var op;if(this.offsetPaddings){op={};pvc.Sides.names.forEach(function(side){var len_a=pvc.BasePanel.orthogonalLength[side];op[side]=(this.offsetPaddings[side]||0)*(clientSize[len_a]+paddings[len_a])},this)}var setSide=function(side,padding){if(op){padding+=(op[side]||0)}if(padding<0){padding=0}var value=requestPaddings[side];if(value==null||padding>value){requestPaddings[side]=padding}};var processScene=function(scene){var x=sceneXScale(scene);var y=sceneYScale(scene);var r=Math.sqrt(sizeScale(hasSizeRole?scene.vars.size.value:0));setSide('left',r-x);setSide('bottom',r-y);setSide('right',x+r-xLength);setSide('top',y+r-yLength)};rootScene.children().selectMany(function(seriesScene){return seriesScene.childNodes}).each(processScene)}layoutInfo.requestPaddings=requestPaddings},_createCore:function(){this.base();var myself=this;var chart=this.chart;var rootScene=this._getRootScene();this._finalizeScene(rootScene);this.pvPanel.zOrder(1);this.pvScatterPanel=new pvc.visual.Panel(this,this.pvPanel,{extensionId:'panel'}).lock('data',rootScene.childNodes).pvMark;var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(dotScene){var d={category:dotScene.vars.x.rawValue,value:dotScene.vars.y.rawValue};var pseudo=Object.create(this);pseudo.index=dotScene.dataIndex;return v1f.call(pseudo,d)}}}var isLineNoSelect=chart._canSelectWithFocusWindow();var line=new pvc.visual.Line(this,this.pvScatterPanel,{extensionId:'line',wrapper:wrapper,noTooltip:false,noHover:true,noSelect:isLineNoSelect,showsSelection:!isLineNoSelect}).lock('data',function(seriesScene){return seriesScene.childNodes}).lock('visible',this.linesVisible).override('x',function(){return this.scene.basePosition}).override('y',function(){return this.scene.orthoPosition});this.pvLine=line.pvMark;var dot=new pvc.visual.Dot(this,this.pvLine,{extensionId:'dot',wrapper:wrapper,activeSeriesAware:this.linesVisible}).intercept('visible',function(){return!this.scene.isIntermediate&&this.delegateExtension(true)}).lock('shape',this.dotShape).override('x',function(){return this.scene.basePosition}).override('y',function(){return this.scene.orthoPosition}).override('color',function(type){if(!myself.dotsVisible){var visible=this.scene.isActive||this.scene.isSingle;if(!visible){return pvc.invisibleFill}}return this.base(type)});this.pvDot=dot.pvMark;this.pvDot.rubberBandSelectionMode='center';dot.override('defaultColor',function(type){var color=this.base(type);if(color&&type==='stroke'){color=color.darker()}return color}).override('interactiveColor',function(color,type){if(type==='stroke'&&this.scene.isActive){return color}return this.base(color,type)});if(!rootScene.hasSizeRole){dot.override('baseSize',function(){if(!myself.dotsVisible){if(this.scene.isSingle){var lineWidth=Math.max(myself.pvLine.scene[this.pvMark.index].lineWidth,0.2)/2;return lineWidth*lineWidth}}return this.base()})}else{var sizeAxis=myself.axes.size;if(sizeAxis.scaleUsesAbs()){dot.override('strokeColor',function(){return this.scene.vars.size.value<0?"#000000":this.base()}).optional('lineCap','round').optionalMark('strokeDasharray',function(scene){return scene.vars.size.value<0?'dot':null}).optionalMark('lineWidth',function(scene){return scene.vars.size.value<0?1.8:1.5})}var sizeScale=this.sizeScale;dot.override('baseSize',function(){return sizeScale(this.scene.vars.size.value)}).override('interactiveSize',function(size){if(this.scene.isActive){var radius=Math.sqrt(size)*1.1;return radius*radius}return size});this.pvPanel.borderPanel.overflow("hidden")}if(this.valuesVisible){var extensionIds=['label'];if(this.compatVersion()<=1){extensionIds.push('lineLabel')}this.pvLabel=new pvc.visual.Label(this,this.pvDot.anchor(this.valuesAnchor),{extensionId:extensionIds,wrapper:wrapper}).pvMark.font(this.valuesFont).text(function(scene){return def.string.join(",",scene.vars.x.label,scene.vars.y.label)})}},renderInteractive:function(){this.pvScatterPanel.render()},_getSelectableMarks:function(){var marks=[];marks.push(this.pvDot);if(this.linesVisible){marks.push(this.pvLine)}return marks},_finalizeScene:function(rootScene){var axes=this.axes,sceneBaseScale=axes.base.sceneScale({sceneVarName:'x'}),sceneOrthoScale=axes.ortho.sceneScale({sceneVarName:'y'});rootScene.children().selectMany(function(seriesScene){return seriesScene.childNodes}).each(function(leafScene){leafScene.basePosition=sceneBaseScale(leafScene);leafScene.orthoPosition=sceneOrthoScale(leafScene)});return rootScene},_buildScene:function(hasColorRole,hasSizeRole){var data=this.visibleData();var rootScene=new pvc.visual.Scene(null,{panel:this,group:data});rootScene.hasColorRole=hasColorRole;rootScene.hasSizeRole=hasSizeRole;var roles=this.visualRoles;var colorVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.color,{forceUnbound:!hasColorRole});var sizeVarHelper=new pvc.visual.RoleVarHelper(rootScene,roles.size,{forceUnbound:!hasSizeRole});var xDim=data.owner.dimensions(roles.x.firstDimensionName());var yDim=data.owner.dimensions(roles.y.firstDimensionName());data.children().each(createSeriesScene,this);rootScene.children().each(completeSeriesScenes,this);return rootScene;function createSeriesScene(seriesGroup){var seriesScene=new pvc.visual.Scene(rootScene,{group:seriesGroup});seriesScene.vars.series=pvc.visual.ValueLabelVar.fromComplex(seriesGroup);colorVarHelper.onNewScene(seriesScene,false);seriesGroup.datums().each(function(datum,dataIndex){var xAtom=datum.atoms[xDim.name];if(xAtom.value==null){return}var yAtom=datum.atoms[yDim.name];if(yAtom.value==null){return}var scene=new pvc.visual.Scene(seriesScene,{datum:datum});scene.dataIndex=dataIndex;scene.vars.x=Object.create(xAtom);scene.vars.y=Object.create(yAtom);sizeVarHelper.onNewScene(scene,true);colorVarHelper.onNewScene(scene,true);scene.isIntermediate=false})}function completeSeriesScenes(seriesScene){var seriesScenes=seriesScene.childNodes,fromScene;for(var c=0,toChildIndex=0,pointCount=seriesScenes.length;c=1&&isFinite(colCount)||def.assert("Must be at least 1 and finite");var rowCount=Math.ceil(count/colCount);rowCount>=1||def.assert("Must be at least 1");var coordRootAxesByScopeType=this._getCoordinatedRootAxesByScopeType();var coordScopesByType,addChartToScope,indexChartByScope;if(coordRootAxesByScopeType){coordScopesByType={};addChartToScope=function(childChart,scopeType,scopeIndex){var scopes=def.array.lazy(coordScopesByType,scopeType);def.array.lazy(scopes,scopeIndex).push(childChart)};indexChartByScope=function(childChart){if(coordRootAxesByScopeType.row){addChartToScope(childChart,'row',childChart.smallRowIndex)}if(coordRootAxesByScopeType.column){addChartToScope(childChart,'column',childChart.smallColIndex)}if(coordRootAxesByScopeType.global){addChartToScope(childChart,'global',0)}}}var childOptionsBase=this._buildSmallChartsBaseOptions();var ChildClass=chart.constructor;for(var index=0;index0){margins.left=smallMargins.left}if(colIndex0){margins.top=smallMargins.top}if(rowIndex1)?elements[1]:"";return item2});for(i=0;itheMax){theMax2=theMax;theMax=v}}}else{theMin=theMax=theMin2=theMax2=values[index][0];for(k=1;ktheMax){theMax2=theMax;theMax=v}}}var theStep=((theMax-theMax2)+(theMin2-theMin))/2;item.min=theMin;item.max=theMax;item.step=theStep;item.categorical=false;if(pCoordMapping[index]){item.map=pCoordMapping[index].map;item.mapLength=pCoordMapping[index].len;item.categorical=pCoordMapping[index].categorical;if(!item.categorical){item.orgValue=[];var theMap=pCoordMapping[index].map;for(var key in theMap){if(theMap.hasOwnProperty(key)){item.orgValue[theMap[key]]=0.0+key}}}}}var genKeyVal=function(keys,vals){var record={};for(var i=0;i=filter[t].min)&&(val<=filter[t].max)})}:function(d){return dims.every(function(t){return(d[t]>=filter[t].min)&&(d[t]<=filter[t].max)})};var auxData=null;this.pvParCoord=this.pvPanel.add(pv.Panel).data(myself.data).visible(selectVisible).add(pv.Line).data(dims).left(function(t,d){return x(t)}).bottom(function(t,d){var res=y[t](d[t]);return res}).strokeStyle("#ddd").lineWidth(1).antialias(false);var rule=this.pvPanel.add(pv.Rule).data(dims).left(x).top(topRuleOffs).bottom(botRuleOffs);rule.anchor("top").add(pv.Label).top(labelTopOffs).font("bold 10px sans-serif").text(function(d){return dimDescr[d].name});var labels=[];var labelXoffs=6,labelYoffs=3;for(var d in dimDescr){if(dimDescr.hasOwnProperty(d)){var dim=dimDescr[d];if(dim.categorical){var xVal=x(dim.id)+labelXoffs;for(var l in dim.map){if(dim.map.hasOwnProperty(l)){labels[labels.length]={x:xVal,y:y[dim.id](dim.map[l])+labelYoffs,label:l}}}}}}var dimLabels=this.pvPanel.add(pv.Panel).data(labels).add(pv.Label).left(function(d){return d.x}).bottom(function(d){return d.y}).text(function(d){return d.label}).textAlign("left");var change=this.pvPanel.add(pv.Panel);var line=change.add(pv.Panel).data(myself.data).visible(selectVisible).add(pv.Line).data(dims).left(function(t,d){return x(t)}).bottom(function(t,d){return y[t](d[t])}).strokeStyle(function(t,d){var dd=dimDescr[active];var val=(dd.orgValue&&!dd.categorical)?dd.orgValue[d[active]]:d[active];return colors[active](val)}).lineWidth(1);function update(d){var t=d.dim;filter[t].min=Math.max(y[t].domain()[0],y[t].invert(height-d.y-d.dy));filter[t].max=Math.min(y[t].domain()[1],y[t].invert(height-d.y));active=t;change.render();return false}function selectAll(d){if(d.dy<3){var t=d.dim;filter[t].min=Math.max(y[t].domain()[0],y[t].invert(0));filter[t].max=Math.min(y[t].domain()[1],y[t].invert(height));d.y=botRuleOffs;d.dy=ruleHeight;active=t;change.render()}return false}var handle=change.add(pv.Panel).data(dims.map(function(dim){return{y:botRuleOffs,dy:ruleHeight,dim:dim}})).left(function(t){return x(t.dim)-30}).width(60).fillStyle("rgba(0,0,0,.001)").cursor("crosshair").event("mousedown",pv.Behavior.select()).event("select",update).event("selectend",selectAll).add(pv.Bar).left(25).top(function(d){return d.y}).width(10).height(function(d){return d.dy}).fillStyle(function(t){return(t.dim==active)?colors[t.dim]((filter[t.dim].max+filter[t.dim].min)/2):"hsla(0,0,50%,.5)"}).strokeStyle("white").cursor("move").event("mousedown",pv.Behavior.drag()).event("dragstart",update).event("drag",update);handle.anchor("bottom").add(pv.Label).textBaseline("top").text(function(d){return(dimDescr[d.dim].categorical)?"":filter[d.dim].min.toFixed(numDigits)+dimDescr[d.dim].unit});handle.anchor("top").add(pv.Label).textBaseline("bottom").text(function(d){return(dimDescr[d.dim].categorical)?"":filter[d.dim].max.toFixed(numDigits)+dimDescr[d.dim].unit});this.extend(this.pvParCoord,"parCoord");this.extend(this.pvPanel,"chart")}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcPieChart.js b/pacotes/ccc2/compacto/pvcPieChart.js deleted file mode 100755 index 243cb88..0000000 --- a/pacotes/ccc2/compacto/pvcPieChart.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.PieChart',pvc.BaseChart).add({_animatable:true,pieChartPanel:null,_getColorRoleSpec:function(){return{isRequired:true,defaultSourceRole:'category',defaultDimension:'color*',requireIsDiscrete:true}},_initVisualRoles:function(){this.base();this._addVisualRole('category',{isRequired:true,defaultDimension:'category*',autoCreateDimension:true});this._addVisualRole('value',{isMeasure:true,isRequired:true,isPercent:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:'value'})},_initPlotsCore:function(){new pvc.visual.PiePlot(this)},_preRenderContent:function(contentOptions){this.base();var isV1Compat=this.compatVersion()<=1;if(isV1Compat){var innerGap=pvc.castNumber(this.options.innerGap)||0.95;innerGap=def.between(innerGap,0.1,1);contentOptions.paddings=((1-innerGap)*100/2).toFixed(2)+"%"}else if(contentOptions.paddings==null){contentOptions.paddings=new pvc.PercentValue(0.025)}var piePlot=this.plots.pie;this.pieChartPanel=new pvc.PieChartPanel(this,this.basePanel,piePlot,def.create(contentOptions,{scenes:def.getPath(this.options,'pie.scenes')}))}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcPiePanel.js b/pacotes/ccc2/compacto/pvcPiePanel.js deleted file mode 100755 index 2f5dca2..0000000 --- a/pacotes/ccc2/compacto/pvcPiePanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.PieChartPanel',pvc.PlotPanel).init(function(chart,parent,plot,options){var labelStyle=plot.option('ValuesLabelStyle');this.base(chart,parent,plot,options);this.explodedOffsetRadius=plot.option('ExplodedSliceRadius');this.explodedSliceIndex=plot.option('ExplodedSliceIndex');this.activeOffsetRadius=plot.option('ActiveSliceRadius');this.labelStyle=labelStyle;if(labelStyle==='linked'){this.linkInsetRadius=plot.option('LinkInsetRadius');this.linkOutsetRadius=plot.option('LinkOutsetRadius');this.linkMargin=plot.option('LinkMargin');this.linkHandleWidth=plot.option('LinkHandleWidth');this.linkLabelSize=plot.option('LinkLabelSize');this.linkLabelSpacingMin=plot.option('LinkLabelSpacingMin')}}).add({pvPie:null,pvPieLabel:null,valueRoleName:'value',_getV1Datum:function(scene){var datum=scene.datum;if(datum){var datumEx=Object.create(datum);datumEx.percent=scene.vars.value.percent;datum=datumEx}return datum},_calcLayout:function(layoutInfo){var clientSize=layoutInfo.clientSize;var clientWidth=clientSize.width;var clientRadius=Math.min(clientWidth,clientSize.height)/2;if(!clientRadius){return new pvc.Size(0,0)}var center=pv.vector(clientSize.width/2,clientSize.height/2);function resolvePercentRadius(radius){return def.between(pvc.PercentValue.resolve(radius,clientRadius),0,clientRadius)}function resolvePercentWidth(width){return def.between(pvc.PercentValue.resolve(width,clientWidth),0,clientWidth)}var labelFont=this._getConstantExtension('label','font');if(!def.string.is(labelFont)){labelFont=this.valuesFont}var maxPieRadius=clientRadius;if(this.valuesVisible&&this.labelStyle==='linked'){var linkInsetRadius=resolvePercentRadius(this.linkInsetRadius);var linkOutsetRadius=resolvePercentRadius(this.linkOutsetRadius);var linkMargin=resolvePercentWidth(this.linkMargin);var linkLabelSize=resolvePercentWidth(this.linkLabelSize);var textMargin=def.number.to(this._getConstantExtension('label','textMargin'),3);var textHeight=pv.Text.fontHeight(labelFont);var linkHandleWidth=this.linkHandleWidth*textHeight;linkMargin+=linkHandleWidth;var linkLabelSpacingMin=this.linkLabelSpacingMin*textHeight;var freeWidthSpace=Math.max(0,clientWidth/2-clientRadius);var spaceH=Math.max(0,linkOutsetRadius+linkMargin+linkLabelSize-freeWidthSpace);var spaceV=linkOutsetRadius+textHeight;var linkAndLabelRadius=Math.max(0,spaceV,spaceH);if(linkAndLabelRadius>=maxPieRadius){this.valuesVisible=false;if(pvc.debug>=2){this._log("Hiding linked labels due to insufficient space.")}}else{maxPieRadius-=linkAndLabelRadius;layoutInfo.link={insetRadius:linkInsetRadius,outsetRadius:linkOutsetRadius,elbowRadius:maxPieRadius+linkOutsetRadius,linkMargin:linkMargin,handleWidth:linkHandleWidth,labelSize:linkLabelSize,maxTextWidth:linkLabelSize-textMargin,labelSpacingMin:linkLabelSpacingMin,textMargin:textMargin,lineHeight:textHeight}}}var explodedOffsetRadius=resolvePercentRadius(this.explodedOffsetRadius);var activeOffsetRadius=0;if(this.chart.options.hoverable){activeOffsetRadius=resolvePercentRadius(this.activeOffsetRadius)}var effectOffsetRadius=explodedOffsetRadius+activeOffsetRadius;var normalPieRadius=maxPieRadius-effectOffsetRadius;if(normalPieRadius<0){return new pvc.Size(0,0)}layoutInfo.center=center;layoutInfo.clientRadius=clientRadius;layoutInfo.normalRadius=normalPieRadius;layoutInfo.explodedOffsetRadius=explodedOffsetRadius;layoutInfo.activeOffsetRadius=activeOffsetRadius;layoutInfo.labelFont=labelFont},_createCore:function(layoutInfo){var myself=this;var chart=this.chart;var options=chart.options;var visibleKeyArgs={visible:true};var rootScene=this._buildScene();var center=layoutInfo.center;var normalRadius=layoutInfo.normalRadius;var wrapper;var extensionIds=['slice'];if(this.compatVersion()<=1){extensionIds.push('');wrapper=function(v1f){return function(pieCatScene){return v1f.call(this,pieCatScene.vars.value.value)}}}this.pvPie=new pvc.visual.PieSlice(this,this.pvPanel,{extensionId:extensionIds,center:center,activeOffsetRadius:layoutInfo.activeOffsetRadius,wrapper:wrapper,tooltipArgs:{options:{useCorners:true,gravity:function(){var isRightPlane=Math.cos(this.midAngle())>=0;var isTopPlane=Math.sin(this.midAngle())>=0;return isRightPlane?(isTopPlane?'nw':'sw'):(isTopPlane?'ne':'se')}}}}).lock('data',rootScene.childNodes).override('angle',function(){return this.scene.vars.value.angle}).override('baseOffsetRadius',function(){var explodeIndex=myself.explodedSliceIndex;if(explodeIndex==null||explodeIndex==this.pvMark.index){return layoutInfo.explodedOffsetRadius}return this.base()}).lock('outerRadius',function(){return chart.animate(0,normalRadius)}).localProperty('innerRadiusEx',pvc.PercentValue.parse).intercept('innerRadius',function(scene){var innerRadius=this.delegateExtension();if(innerRadius==null){var innerRadiusPct=this.pvMark.innerRadiusEx();if(innerRadiusPct!=null){innerRadius=pvc.PercentValue.resolve(innerRadiusPct,this.pvMark.outerRadius())||0}else{innerRadius=0}}return innerRadius>0?chart.animate(0,innerRadius):0}).pvMark;if(this.valuesVisible){if(this.labelStyle==='inside'){this.pvPieLabel=new pvc.visual.Label(this,this.pvPie.anchor(this.valuesAnchor),{extensionId:'label',wrapper:wrapper}).intercept('visible',function(scene){var angle=scene.vars.value.angle;if(angle<0.001){return false}return this.delegateExtension(true)}).pvMark.text(function(scene){return scene.vars.value.sliceLabel}).textMargin(10)}else if(this.labelStyle==='linked'){var linkLayout=layoutInfo.link;rootScene.layoutLinkLabels(layoutInfo);this.pvLinkPanel=this.pvPanel.add(pv.Panel).data(rootScene.childNodes).localProperty('pieSlice').pieSlice(function(scene){return myself.pvPie.scene[this.index]});this.pvLinkLine=new pvc.visual.Line(this,this.pvLinkPanel,{extensionId:'linkLine',freePosition:true,noClick:true,noDoubleClick:true,noSelect:true,noTooltip:true,noHover:true}).lockMark('data',function(scene){var pieSlice=this.parent.pieSlice();var midAngle=pieSlice.startAngle+pieSlice.angle/2;var outerRadius=pieSlice.outerRadius-linkLayout.insetRadius;var x=pieSlice.left+outerRadius*Math.cos(midAngle);var y=pieSlice.top+outerRadius*Math.sin(midAngle);var firstDotScene=scene.childNodes[0];if(!firstDotScene||!firstDotScene._isFirstDynamicScene){firstDotScene=new pvc.visual.PieLinkLineScene(scene,x,y,0);firstDotScene._isFirstDynamicScene=true}else{firstDotScene.x=x;firstDotScene.y=y}return scene.childNodes}).override('defaultColor',function(type){if(type==='stroke'){return'black'}return this.base(type)}).override('defaultStrokeWidth',def.fun.constant(0.5)).pvMark.lock('visible').lock('top',function(dot){return dot.y}).lock('left',function(dot){return dot.x});this.pvPieLabel=new pvc.visual.Label(this,this.pvLinkPanel,{extensionId:'label',noClick:false,noDoubleClick:false,noSelect:false,noHover:false}).lockMark('data',function(scene){return scene.lineScenes}).pvMark.lock('visible').left(function(scene){return scene.vars.link.labelX}).top(function(scene){return scene.vars.link.labelY+((this.index+1)*linkLayout.lineHeight)}).textAlign(function(scene){return scene.vars.link.labelAnchor}).textMargin(linkLayout.textMargin).textBaseline('bottom').text(function(scene){return scene.vars.link.labelLines[this.index]}).fillStyle('red');if(pvc.debug>=20){this.pvPanel.add(pv.Panel).zOrder(-10).left(center.x-layoutInfo.clientRadius).top(center.y-layoutInfo.clientRadius).width(layoutInfo.clientRadius*2).height(layoutInfo.clientRadius*2).strokeStyle('red');this.pvPanel.strokeStyle('green');var linkColors=pv.Colors.category10();this.pvLinkLine.segmented(true).strokeStyle(function(){return linkColors(this.index)})}}this.pvPieLabel.font(layoutInfo.labelFont)}},_getExtensionId:function(){var extensionIds=[{abs:'content'}];if(this.chart.parent){extensionIds.push({abs:'smallContent'})}return extensionIds.concat(this.base())},renderInteractive:function(){this.pvPanel.render()},_getSelectableMarks:function(){var marks=[this.pvPie];if(this.pvPieLabel){marks.push(this.pvPieLabel)}return marks},_buildScene:function(){var rootScene=new pvc.visual.PieRootScene(this);this.sum=rootScene.vars.sumAbs.value;return rootScene}});def.type('pvc.visual.PieRootScene',pvc.visual.Scene).init(function(panel){var chart=panel.chart;var data=chart.visualRoles('category').flatten(chart.data,pvc.data.visibleKeyArgs);var colorVarHelper=new pvc.visual.RoleVarHelper(chart,chart._colorRole);this.base(null,{panel:panel,group:data});var valueRoleName=panel.valueRoleName;var valueDimName=chart.visualRoles(valueRoleName).firstDimensionName();var valueDim=data.dimensions(valueDimName);var options=chart.options;var percentValueFormat=options.percentValueFormat;var rootScene=this;var sumAbs=0;var CategSceneClass=def.type(pvc.visual.PieCategoryScene).init(function(categData,value){this.base(rootScene,{group:categData});this.vars.category=pvc.visual.ValueLabelVar.fromComplex(categData);sumAbs+=Math.abs(value);this.vars.value=new pvc.visual.ValueLabelVar(value,formatValue(value,categData));colorVarHelper.onNewScene(this,true)});panel._extendSceneType('category',CategSceneClass,['sliceLabel','sliceLabelMask']);data.children().each(function(categData){var value=categData.dimensions(valueDimName).sum(pvc.data.visibleKeyArgs);if(value!==0){new CategSceneClass(categData,value)}});this.angleScale=pv.Scale.linear(0,sumAbs).range(0,2*Math.PI).by1(Math.abs);this.vars.sumAbs=new pvc.visual.ValueLabelVar(sumAbs,formatValue(sumAbs));this.childNodes.forEach(function(categScene){completeBuildCategScene.call(categScene)});function formatValue(value,categData){if(categData){var datums=categData._datums;if(datums.length===1){return datums[0].atoms[valueDimName].label}}return valueDim.format(value)}function completeBuildCategScene(){var valueVar=this.vars.value;valueVar.angle=this.parent.angleScale(valueVar.value);var percent=Math.abs(valueVar.value)/sumAbs;valueVar.percent=new pvc.visual.ValueLabelVar(percent,percentValueFormat(percent));valueVar.sliceLabel=this.sliceLabel()}}).add({layoutLinkLabels:function(layoutInfo){var startAngle=-Math.PI/2;var leftScenes=[];var rightScenes=[];this.childNodes.forEach(function(categScene){startAngle=categScene.layoutI(layoutInfo,startAngle);(categScene.vars.link.dir>0?rightScenes:leftScenes).push(categScene)});this._distributeLabels(-1,leftScenes,layoutInfo);this._distributeLabels(+1,rightScenes,layoutInfo)},_distributeLabels:function(dir,scenes,layoutInfo){scenes.sort(function(sceneA,sceneB){return def.compare(sceneA.vars.link.targetY,sceneB.vars.link.targetY)});this._distributeLabelsDownwards(scenes,layoutInfo)&&this._distributeLabelsUpwards(scenes,layoutInfo)&&this._distributeLabelsEvenly(scenes,layoutInfo);scenes.forEach(function(categScene){categScene.layoutII(layoutInfo)})},_distributeLabelsDownwards:function(scenes,layoutInfo){var linkLayout=layoutInfo.link;var labelSpacingMin=linkLayout.labelSpacingMin;var yMax=layoutInfo.clientSize.height;var overlapping=false;for(var i=0,J=scenes.length-1;itargetYMax){overlapping=true;linkVar1.targetY=targetYMax}else{linkVar1.targetY=targetY1}}}return overlapping},_distributeLabelsUpwards:function(scenes,layoutInfo){var linkLayout=layoutInfo.link;var labelSpacingMin=linkLayout.labelSpacingMin;var overlapping=false;for(var i=scenes.length-1;i>0;i--){var linkVar1=scenes[i-1].vars.link;var linkVar0=scenes[i].vars.link;if(i===1&&linkVar1.labelTop()<0){overlapping=true}var labelBottomMax1=linkVar0.labelTop()-labelSpacingMin;if(linkVar1.labelBottom()>labelBottomMax1){var halfLabelHeight1=linkVar1.labelHeight/2;var targetY1=labelBottomMax1-halfLabelHeight1;var targetYMin=halfLabelHeight1;if(targetY11){labelSpacing/=(scenes.length-1)}var y=0;scenes.forEach(function(scene){var linkVar=scene.vars.link;var halfLabelHeight=linkVar.labelHeight/2;y+=halfLabelHeight;linkVar.targetY=y;y+=halfLabelHeight+labelSpacing});return true}});def.type('pvc.visual.PieLinkLabelVar').add({labelTop:function(){return this.targetY-this.labelHeight/2},labelBottom:function(){return this.targetY+this.labelHeight/2}});def.type('pvc.visual.PieCategoryScene',pvc.visual.Scene).add({sliceLabelMask:function(){return this.panel().valuesMask},sliceLabel:function(){return this.format(this.sliceLabelMask())},layoutI:function(layoutInfo,startAngle){var valueVar=this.vars.value;var endAngle=startAngle+valueVar.angle;var midAngle=(startAngle+endAngle)/2;var linkVar=(this.vars.link=new pvc.visual.PieLinkLabelVar());var linkLayout=layoutInfo.link;var labelLines=pvc.text.justify(valueVar.sliceLabel,linkLayout.maxTextWidth,layoutInfo.labelFont);var lineCount=labelLines.length;linkVar.labelLines=labelLines;linkVar.labelHeight=lineCount*linkLayout.lineHeight;this.lineScenes=def.array.create(lineCount,this);var cosMid=Math.cos(midAngle);var sinMid=Math.sin(midAngle);var isAtRight=cosMid>=0;var dir=isAtRight?1:-1;linkVar.labelAnchor=isAtRight?'left':'right';var center=layoutInfo.center;var elbowRadius=linkLayout.elbowRadius;var elbowX=center.x+elbowRadius*cosMid;var elbowY=center.y+elbowRadius*sinMid;var anchorX=center.x+dir*elbowRadius;var targetX=anchorX+dir*linkLayout.linkMargin;new pvc.visual.PieLinkLineScene(this,elbowX,elbowY);new pvc.visual.PieLinkLineScene(this,anchorX,elbowY);linkVar.elbowY=elbowY;linkVar.targetY=elbowY+0;linkVar.targetX=targetX;linkVar.dir=dir;return endAngle},layoutII:function(layoutInfo){var linkVar=this.vars.link;var targetY=linkVar.targetY;var targetX=linkVar.targetX;var handleWidth=layoutInfo.link.handleWidth;if(handleWidth>0){new pvc.visual.PieLinkLineScene(this,targetX-linkVar.dir*handleWidth,targetY)}new pvc.visual.PieLinkLineScene(this,targetX,targetY);linkVar.labelX=targetX;linkVar.labelY=targetY-linkVar.labelHeight/2}});def.type('pvc.visual.PieLinkLineScene',pvc.visual.Scene).init(function(catScene,x,y,index){this.base(catScene,{group:catScene.group,index:index});this.x=x;this.y=y}).add(pv.Vector); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcPlotBgPanel.js b/pacotes/ccc2/compacto/pvcPlotBgPanel.js deleted file mode 100755 index e962fc4..0000000 --- a/pacotes/ccc2/compacto/pvcPlotBgPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.PlotBgPanel',pvc.BasePanel).init(function(chart,parent,options){this.base(chart,parent,options)}).add({anchor:'fill',_getExtensionId:function(){return'plotBg'},_createCore:function(layoutInfo){this.pvPanel.borderPanel.lock('zOrder',-13).antialias(false);this.base(layoutInfo)}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcPlotPanel.js b/pacotes/ccc2/compacto/pvcPlotPanel.js deleted file mode 100755 index be98f8c..0000000 --- a/pacotes/ccc2/compacto/pvcPlotPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.PlotPanel',pvc.BasePanel).init(function(chart,parent,plot,options){this.base(chart,parent,options);this.plot=plot;this._extensionPrefix=plot.extensionPrefixes;this.dataPartValue=plot.option('DataPart');this.axes.color=chart._getAxis('color',(plot.option('ColorAxis')||0)-1);this.orientation=plot.option('Orientation');this.valuesVisible=plot.option('ValuesVisible');this.valuesAnchor=plot.option('ValuesAnchor');this.valuesMask=plot.option('ValuesMask');this.valuesFont=plot.option('ValuesFont');var roles=this.visualRoles=Object.create(chart._visualRoles);var colorRoleName=plot.option('ColorRole');roles.color=colorRoleName?chart.visualRoles(colorRoleName):null;this.chart._addPlotPanel(this)}).add({anchor:'fill',visualRoles:null,_getExtensionId:function(){var extensionIds=['chart','plot'];if(this.plotName){extensionIds.push(this.plotName)}return extensionIds},isOrientationVertical:function(){return this.orientation===pvc.orientation.vertical},isOrientationHorizontal:function(){return this.orientation===pvc.orientation.horizontal}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcPoint.js b/pacotes/ccc2/compacto/pvcPoint.js deleted file mode 100755 index 46665e1..0000000 --- a/pacotes/ccc2/compacto/pvcPoint.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.PointAbstract',pvc.CategoricalAbstract).add({_animatable:true,_processOptionsCore:function(options){options.panelSizeRatio=1;this.base(options)},_hasDataPartRole:function(){return true},_initVisualRoles:function(){this.base();this._addVisualRole('value',{isMeasure:true,isRequired:true,isPercent:this.options.stacked,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:'value'})},_initPlotsCore:function(){var options=this.options;var pointPlot=this._createPointPlot();var trend=pointPlot.option('Trend');if(options.plot2){var plot2Plot=new pvc.visual.PointPlot(this,{name:'plot2',fixed:{DataPart:'1'},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:true}});if(!trend){trend=plot2Plot.option('Trend')}}if(trend){new pvc.visual.PointPlot(this,{name:'trend',fixed:{DataPart:'trend',TrendType:'none',ColorRole:'series',NullInterpolatioMode:'none'},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:false}})}},_bindAxes:function(hasMultiRole){this.base(hasMultiRole);var typeAxes=this.axesByType.base;if(typeAxes){typeAxes.forEach(function(axis){var isDiscrete=axis.scaleType==='discrete';if(!isDiscrete){axis.option.defaults({Offset:0.01})}})}typeAxes=this.axesByType.ortho;if(typeAxes){typeAxes.forEach(function(axis){axis.option.defaults({Offset:0.04})})}},_createPlotPanels:function(parentPanel,baseOptions){var plots=this.plots;var pointPlot=plots.point;this.scatterChartPanel=new pvc.PointPanel(this,parentPanel,pointPlot,Object.create(baseOptions));var plot2Plot=plots.plot2;if(plot2Plot){if(pvc.debug>=3){this._log("Creating second Point panel.")}new pvc.PointPanel(this,parentPanel,plot2Plot,Object.create(baseOptions))}var trendPlot=plots.trend;if(trendPlot){if(pvc.debug>=3){this._log("Creating Trends Point panel.")}new pvc.PointPanel(this,parentPanel,trendPlot,Object.create(baseOptions))}},defaults:{tooltipOffset:10}});def.type('pvc.DotChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{DotsVisible:true}})}});def.type('pvc.LineChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{LinesVisible:true}})}});def.type('pvc.AreaChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{AreasVisible:true}})}});pvc.mStackedLineChart=def.type('pvc.StackedLineChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{LinesVisible:true,Stacked:true}})}});def.type('pvc.StackedDotChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{DotsVisible:true,Stacked:true}})}});pvc.mStackedAreaChart=def.type('pvc.StackedAreaChart',pvc.PointAbstract).add({_createPointPlot:function(){return new pvc.visual.PointPlot(this,{fixed:{AreasVisible:true,Stacked:true},defaults:{LinesVisible:true}})}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcPointPanel.js b/pacotes/ccc2/compacto/pvcPointPanel.js deleted file mode 100755 index 8b8ed11..0000000 --- a/pacotes/ccc2/compacto/pvcPointPanel.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.PointPanel',pvc.CategoricalAbstractPanel).init(function(chart,parent,plot,options){this.base(chart,parent,plot,options);this.linesVisible=plot.option('LinesVisible');this.dotsVisible=plot.option('DotsVisible');this.areasVisible=plot.option('AreasVisible');if(!this.linesVisible&&!this.dotsVisible&&!this.areasVisible){this.linesVisible=true;plot.option.specify({'LinesVisible':true})}}).add({pvLine:null,pvArea:null,pvDot:null,pvLabel:null,pvScatterPanel:null,_creating:function(){var groupScene=this.defaultVisibleBulletGroupScene();if(groupScene&&!groupScene.hasRenderer()){var colorAxis=groupScene.colorAxis;var drawMarker=def.nullyTo(colorAxis.option('LegendDrawMarker',true),this.dotsVisible||this.areasVisible);var drawRule=!drawMarker||def.nullyTo(colorAxis.option('LegendDrawLine',true),this.linesVisible&&!this.areasVisible);if(drawMarker||drawRule){var keyArgs={};if((keyArgs.drawMarker=drawMarker)){var markerShape=colorAxis.option('LegendShape',true);if(this.dotsVisible){if(!markerShape){markerShape='circle'}keyArgs.markerPvProto=new pv.Dot().lineWidth(1.5,pvc.extensionTag).shapeSize(12,pvc.extensionTag)}else{keyArgs.markerPvProto=new pv.Mark()}keyArgs.markerShape=markerShape;if(this._applyV1BarSecondExtensions){this.chart.extend(keyArgs.markerPvProto,'barSecondDot',{constOnly:true})}this.extend(keyArgs.markerPvProto,'dot',{constOnly:true})}if((keyArgs.drawRule=drawRule)){keyArgs.rulePvProto=new pv.Line().lineWidth(1.5,pvc.extensionTag);if(this._applyV1BarSecondExtensions){this.chart.extend(keyArgs.rulePvProto,'barSecondLine',{constOnly:true})}this.extend(keyArgs.rulePvProto,'line',{constOnly:true})}groupScene.renderer(new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs))}}},_createCore:function(){this.base();var myself=this;var chart=this.chart;var isStacked=this.stacked;var dotsVisible=this.dotsVisible;var areasVisible=this.areasVisible;var linesVisible=this.linesVisible;var anchor=this.isOrientationVertical()?"bottom":"left";this.valueRole=chart.visualRoles(this.plot.option('OrthoRole'));this.valueRoleName=this.valueRole.name;this.valueDimName=this.valueRole.firstDimensionName();var isBaseDiscrete=this.axes.base.role.grouping.isDiscrete();var data=this.visibleData();var rootScene=this._buildScene(data,isBaseDiscrete);if(areasVisible){this.pvPanel.zOrder(-7)}else{this.pvPanel.zOrder(1)}this.pvScatterPanel=new pvc.visual.Panel(this,this.pvPanel,{extensionId:'panel'}).lock('data',rootScene.childNodes).pvMark;var areaFillColorAlpha=areasVisible&&linesVisible&&!isStacked?0.5:null;var wrapper;if(this.compatVersion()<=1){if(isStacked){wrapper=function(v1f){return function(dotScene){return v1f.call(this,dotScene.vars.value.rawValue)}}}else{wrapper=function(v1f){return function(dotScene){var d={category:dotScene.vars.category.rawValue,value:dotScene.vars.value.rawValue};var pseudo=Object.create(this);pseudo.index=dotScene.dataIndex;return v1f.call(pseudo,d)}}}}var isLineAreaVisible=isBaseDiscrete&&isStacked?function(){return!this.scene.isNull||this.scene.isIntermediate}:function(){return!this.scene.isNull};var isLineAreaNoSelect=chart._canSelectWithFocusWindow();this.pvArea=new pvc.visual.Area(this,this.pvScatterPanel,{extensionId:'area',noTooltip:false,wrapper:wrapper,noSelect:isLineAreaNoSelect,showsSelection:!isLineAreaNoSelect}).lock('visible',isLineAreaVisible).lock('data',function(seriesScene){return seriesScene.childNodes}).override('x',function(){return this.scene.basePosition}).override('y',function(){return this.scene.orthoPosition}).override('dy',function(){return chart.animate(0,this.scene.orthoLength)}).override('color',function(type){return areasVisible?this.base(type):null}).override('baseColor',function(type){var color=this.base(type);if(!this._finished&&color&&areaFillColorAlpha!=null){color=color.alpha(areaFillColorAlpha)}return color}).override('dimColor',function(color,type){return isStacked?pvc.toGrayScale(color,1,null,null).brighter():this.base(color,type)}).lock('events',areasVisible?'painted':'none').pvMark;var dotsVisibleOnly=dotsVisible&&!linesVisible&&!areasVisible,lineCopiesAreaColor=!linesVisible&&areasVisible,darkerLineAndDotColor=isStacked&&areasVisible;var extensionIds=['line'];if(this._applyV1BarSecondExtensions){extensionIds.push({abs:'barSecondLine'})}var isLineVisible=!dotsVisibleOnly&&isLineAreaVisible;this.pvLine=new pvc.visual.Line(this,this.pvArea.anchor(this.anchorOpposite(anchor)),{extensionId:extensionIds,freePosition:true,wrapper:wrapper,noTooltip:false,noSelect:isLineAreaNoSelect,showsSelection:!isLineAreaNoSelect}).lock('visible',isLineVisible).override('defaultColor',function(type){var color=this.base(type);if(!this._finished&&darkerLineAndDotColor&&color){color=color.darker(0.6)}return color}).override('normalColor',function(color,type){return linesVisible?color:null}).override('baseStrokeWidth',function(){var strokeWidth;if(linesVisible){strokeWidth=this.base()}return strokeWidth==null?1.5:strokeWidth}).intercept('strokeDasharray',function(){var dashArray=this.delegateExtension();if(dashArray===undefined){var scene=this.scene;var useDash=scene.isInterpolated;if(!useDash){var next=scene.nextSibling;useDash=next&&next.isIntermediate&&next.isInterpolated;if(!useDash){var previous=scene.previousSibling;useDash=previous&&scene.isIntermediate&&previous.isInterpolated}}dashArray=useDash?'. ':null}return dashArray}).pvMark;var showAloneDots=!(areasVisible&&isBaseDiscrete&&isStacked);extensionIds=['dot'];if(this._applyV1BarSecondExtensions){extensionIds.push({abs:'barSecondDot'})}this.pvDot=new pvc.visual.Dot(this,this.pvLine,{extensionId:extensionIds,freePosition:true,wrapper:wrapper}).intercept('visible',function(){var scene=this.scene;return(!scene.isNull&&!scene.isIntermediate)&&this.delegateExtension(true)}).override('color',function(type){if(!dotsVisible){var visible=this.scene.isActive||(!showAloneDots&&this.scene.isSingle)||(showAloneDots&&this.scene.isAlone);if(!visible){return pvc.invisibleFill}}if(this.scene.isInterpolated&&type==='fill'){var color=this.base(type);return color&&pv.color(color).brighter(0.5)}return this.base(type)}).optionalMark('lineCap','round').override('defaultColor',function(type){var color=this.base(type);if(!this._finished&&darkerLineAndDotColor&&color){color=color.darker(0.6)}return color}).override('baseSize',function(){if(!dotsVisible){var visible=this.scene.isActive||(!showAloneDots&&this.scene.isSingle)||(showAloneDots&&this.scene.isAlone);if(visible&&!this.scene.isActive){var lineWidth=Math.max(myself.pvLine.lineWidth(),0.2)/2;return lineWidth*lineWidth}}if(this.scene.isInterpolated){return 0.8*this.base()}return this.base()}).pvMark;if(this.valuesVisible){this.pvLabel=new pvc.visual.Label(this,this.pvDot.anchor(this.valuesAnchor),{extensionId:'label',wrapper:wrapper}).pvMark.font(this.valuesFont).text(function(scene){return scene.vars.value.label})}},renderInteractive:function(){this.pvScatterPanel.render()},_getSelectableMarks:function(){var marks=[];marks.push(this.pvDot);if(this.linesVisible||this.areasVisible){marks.push(this.pvLine)}return marks},_buildScene:function(data,isBaseDiscrete){var rootScene=new pvc.visual.Scene(null,{panel:this,group:data});var categDatas=data._children;var chart=this.chart;var colorVarHelper=new pvc.visual.RoleVarHelper(chart,chart._colorRole);var valueDim=data.owner.dimensions(this.valueDimName);var isStacked=this.stacked;var visibleKeyArgs={visible:true,zeroIfNone:false};var orthoScale=this.axes.ortho.scale;var orthoNullValue=def.scope(function(){var domain=orthoScale.domain(),dmin=domain[0],dmax=domain[1];if(dmin*dmax>=0){return dmin>=0?dmin:dmax}return 0});var orthoZero=orthoScale(orthoNullValue);var sceneBaseScale=this.axes.base.sceneScale({sceneVarName:'category'});def.scope(function(){var serRole=chart._serRole;return(serRole&&serRole.grouping)?serRole.flatten(data).children():def.query([null])}).each(function(seriesData1){var seriesScene=new pvc.visual.Scene(rootScene,{group:seriesData1||data});seriesScene.vars.series=pvc.visual.ValueLabelVar.fromComplex(seriesData1);colorVarHelper.onNewScene(seriesScene,false);categDatas.forEach(function(categData,categIndex){var group=categData;if(seriesData1){group=group._childrenByKey[seriesData1.key]}var value=group?group.dimensions(valueDim.name).sum(visibleKeyArgs):null;var serCatScene=new pvc.visual.Scene(seriesScene,{group:group});serCatScene.dataIndex=categIndex;serCatScene.vars.category=pvc.visual.ValueLabelVar.fromComplex(categData);var valueVar=new pvc.visual.ValueLabelVar(value,valueDim.format(value),value);valueVar.accValue=value!=null?value:orthoNullValue;serCatScene.vars.value=valueVar;colorVarHelper.onNewScene(serCatScene,true);var isInterpolated=false;if(group){var firstDatum=group._datums[0];if(firstDatum&&firstDatum.isInterpolated){isInterpolated=true}}serCatScene.isInterpolated=isInterpolated;serCatScene.isNull=value==null;serCatScene.isIntermediate=false},this)},this);var reversedSeriesScenes=rootScene.children().reverse().array();var belowSeriesScenes2;reversedSeriesScenes.forEach(completeSeriesScenes,this);reversedSeriesScenes.forEach(trimNullSeriesScenes,this);return rootScene;function completeSeriesScenes(seriesScene){var seriesScenes2=[],seriesScenes=seriesScene.childNodes,fromScene,notNullCount=0,firstAloneScene=null;for(var c=0,toChildIndex=0,categCount=seriesScenes.length;cclientWidth?clientWidth:textWidth}else if(desiredWidth>clientWidth){desiredWidth=clientWidth}var lines;if(textWidth>desiredWidth){lines=pvc.text.justify(this.title,desiredWidth,this.font)}else{lines=this.title?[this.title]:[]}var lineHeight=pv.Text.fontHeight(this.font);var realHeight=lines.length*lineHeight;var availableHeight=layoutInfo.clientSize[a_height];var desiredHeight=layoutInfo.desiredClientSize[a_height];if(desiredHeight==null){desiredHeight=realHeight}else if(desiredHeight>availableHeight){desiredHeight=availableHeight}if(realHeight>desiredHeight){var maxLineCount=Math.max(1,Math.floor(desiredHeight/lineHeight));if(lines.length>maxLineCount){var firstCroppedLine=lines[maxLineCount];lines.length=maxLineCount;realHeight=desiredHeight=maxLineCount*lineHeight;var lastLine=lines[maxLineCount-1]+" "+firstCroppedLine;lines[maxLineCount-1]=pvc.text.trimToWidthB(desiredWidth,lastLine,this.font,"..")}}layoutInfo.lines=lines;layoutInfo.topOffset=(desiredHeight-realHeight)/2;layoutInfo.lineSize={width:desiredWidth,height:lineHeight};layoutInfo.a_width=a_width;layoutInfo.a_height=a_height;requestSize[a_width]=desiredWidth;requestSize[a_height]=desiredHeight;return requestSize},_createCore:function(layoutInfo){var rootScene=this._buildScene(layoutInfo);var rotationByAnchor={top:0,right:Math.PI/2,bottom:0,left:-Math.PI/2};var textAlign=pvc.BasePanel.horizontalAlign[this.align];var textAnchor=pvc.BasePanel.leftTopAnchor[this.anchor];var wrapper;if(this.compatVersion()<=1){wrapper=function(v1f){return function(itemScene){return v1f.call(this)}}}this.pvLabel=new pvc.visual.Label(this,this.pvPanel,{extensionId:'label',wrapper:wrapper}).lock('data',rootScene.lineScenes).pvMark[textAnchor](function(lineScene){return layoutInfo.topOffset+lineScene.vars.size.height/2+this.index*lineScene.vars.size.height}).textAlign(textAlign)[this.anchorOrtho(textAnchor)](function(lineScene){switch(this.textAlign()){case'center':return lineScene.vars.size.width/2;case'left':return 0;case'right':return lineScene.vars.size.width}}).text(function(lineScene){return lineScene.vars.textLines[this.index]}).font(this.font).textBaseline('middle').textAngle(rotationByAnchor[this.anchor])},_buildScene:function(layoutInfo){var rootScene=new pvc.visual.Scene(null,{panel:this,group:this.chart.data});var textLines=layoutInfo.lines;rootScene.vars.size=layoutInfo.lineSize;rootScene.vars.textLines=textLines;rootScene.lineScenes=def.array.create(textLines.length,rootScene);return rootScene},_getExtensionId:function(){return''}}); \ No newline at end of file diff --git a/pacotes/ccc2/compacto/pvcWaterfallChart.js b/pacotes/ccc2/compacto/pvcWaterfallChart.js deleted file mode 100755 index 88c01bd..0000000 --- a/pacotes/ccc2/compacto/pvcWaterfallChart.js +++ /dev/null @@ -1 +0,0 @@ -def.type('pvc.WaterfallChart',pvc.BarAbstract).init(function(options){this.base(options);var parent=this.parent;if(parent){this._isFalling=parent._isFalling}}).add({_animatable:true,_isFalling:true,_ruleInfos:null,_waterColor:pv.color("#1f77b4").darker(),_processOptionsCore:function(options){options.stacked=true;options.baseAxisComposite=false;this.base(options);options.plot2=false},_initPlotsCore:function(){var options=this.options;var waterPlot=new pvc.visual.WaterfallPlot(this);this._isFalling=waterPlot.option('Direction')==='down';this._catRole.setFlatteningMode(this._isFalling?'tree-pre':'tree-post');this._catRole.setFlattenRootLabel(this.plots.water.option('AllCategoryLabel'))},_initLegendScenes:function(legendPanel){var waterPlot=this.plots.water;var extAbsId=pvc.makeExtensionAbsId('line',waterPlot.extensionPrefixes);var strokeStyle=this._getConstantExtension(extAbsId,"strokeStyle");if(strokeStyle){this._waterColor=pv.color(strokeStyle)}var rootScene=legendPanel._getBulletRootScene();new pvc.visual.legend.WaterfallBulletGroupScene(rootScene,{extensionPrefix:pvc.buildIndexedId('',1),label:waterPlot.option('TotalLineLabel'),color:this._waterColor});this.base(legendPanel)},_reduceStackedCategoryValueExtent:function(result,catRange,catGroup){var offset;if(!result){if(catRange){offset=catRange.min+catRange.max;this._ruleInfos=[{offset:offset,group:catGroup,range:catRange}];return{min:catRange.min,max:catRange.max,offset:offset}}return null}offset=result.offset;if(this._isFalling){this._ruleInfos.push({offset:offset,group:catGroup,range:catRange})}if(!catGroup._isFlattenGroup||catGroup._isDegenerateFlattenGroup){var dir=this._isFalling?-1:1;offset=result.offset=offset+dir*(catRange.min+catRange.max);if(offset>result.max){result.max=offset}if(offset=6&&gravity!==bestScore.gravity){_tip.log("[TIPSY] #"+_tipsyId+" Choosing gravity '"+bestScore.gravity+"' over '"+gravity+"'")}gravity=bestScore.gravity}if(_tip.debug>=6){_tip.log("[TIPSY] #"+_tipsyId+" Gravity '"+gravity+"'")}return gravity;function scoreGravity(gravity){var tp=calcPosition(gravity);return scorePosition(gravity,tp)}function scorePosition(gravity,tp){var wScore=calcPosScore(tp.left,'width');var hScore=calcPosScore(tp.top,'height');var isTotal=wScore.fits&&hScore.fits;return{gravity:gravity,width:wScore,height:hScore,value:wScore.value+hScore.value+(2-gravity.length),isTotal:isTotal,isPartial:!isTotal&&(wScore.fits||hScore.fits)}}function calcPosScore(absPos,a_len){var maxLen=pageSize[a_len];var len=tipSize[a_len];var pos=absPos-scrollOffset[a_len];var opos=maxLen-(pos+len);var fits=pos>=0&&opos>=0;var value=(pos>=0?pos:(4*pos))+(opos>=0?opos:(4*opos));return{fits:fits,value:value}}}function chooseScores(score1,score2){if(score1.isTotal){if(!score2.isTotal){return score1}}else if(score2.isTotal){if(!score1.isTotal){return score2}}else if(score1.isPartial){if(!score2.isPartial){return score1}}else if(score2.isPartial){if(!score1.isPartial){return score2}}return score2.value>score1.value?score2:score1}function setFakeTipTargetBounds(bounds){$fakeTipTarget.css({left:bounds.left+parseFloat($canvas.css("padding-left")),top:bounds.top+parseFloat($canvas.css("padding-top")),width:bounds.width,height:bounds.height})}function createTipsy(mark){var c=mark.root.canvas();$canvas=$(c);c.style.position="relative";$canvas.mouseleave(hideTipsy);initTipsyCanvasSharedInfo();if(!id){id="tipsyPvBehavior_"+new Date().getTime()}var fakeTipTarget=document.getElementById(id);if(!fakeTipTarget){fakeTipTarget=document.createElement("div");fakeTipTarget.id=id;c.appendChild(fakeTipTarget)}var fakeStyle=fakeTipTarget.style;fakeStyle.padding='0px';fakeStyle.margin='0px';fakeStyle.position='absolute';fakeStyle.pointerEvents='none';fakeStyle.display='block';fakeStyle.zIndex=-10;$fakeTipTarget=$(fakeTipTarget);updateTipDebug();$fakeTipTarget.data('tipsy',null);$fakeTipTarget.tipsy(opts)}function initTipsyCanvasSharedInfo(){sharedTipsyInfo=$canvas.data('tipsy-pv-shared-info');if(sharedTipsyInfo){var createId=($canvas[0].$pvCreateId||0);if(sharedTipsyInfo.createId===createId){sharedTipsyInfo.behaviors.push(hideTipsyOther);return}sharedTipsyInfo.behaviors.forEach(function(aHideTipsy){aHideTipsy()})}sharedTipsyInfo={createId:($canvas[0].$pvCreateId||0),behaviors:[hideTipsyOther]};$canvas.data('tipsy-pv-shared-info',sharedTipsyInfo)}function updateTipDebug(){if($fakeTipTarget){if(_tip.debug>=16){$fakeTipTarget.css({borderColor:'red',borderWidth:'1px',borderStyle:'solid',zIndex:1000})}else{$fakeTipTarget.css({borderWidth:'0px',zIndex:-10})}}}function getMouseBounds(ev){if(!ev){ev=pv.event}var delta=5;var offset=$canvas.offset();return{left:ev.pageX-offset.left-delta,top:ev.pageY-offset.top-delta,width:10+2*delta,height:20}}function setTarget(targetElem,mark){if((!$targetElem&&targetElem)||($targetElem&&$targetElem[0]!==targetElem)){if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Changing target element.")}if($targetElem){$targetElem.unbind('mousemove',updateTipsy);if(!usesPoint){$targetElem.unbind('mouseleave',hideTipsy)}}$targetElem=targetElem?$(targetElem):null;_mark=targetElem?mark:null;prevMouseX=prevMouseY=_renderId=null;if($targetElem){$targetElem.mousemove(updateTipsy);if(!usesPoint){$targetElem.mouseleave(hideTipsy)}}}}function getNewOperationId(){return nextOperationId++}function checkCanOperate(opId){return opId===nextOperationId-1}function hideTipsy(){var opId=getNewOperationId();if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Delayed Hide Begin opId="+opId)}if(delayOut>0){window.setTimeout(function(){if(checkCanOperate(opId)){if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Hiding opId="+opId+" nextOperationId="+nextOperationId)}hideTipsyCore(opId)}else{if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Delayed Hide Cancelled opId="+opId)}}},delayOut);return}if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Hiding Immediately opId="+opId)}hideTipsyCore(opId)}function hideTipsyOther(){var opId=getNewOperationId();if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Hiding as Other opId="+opId)}hideTipsyCore(opId)}function hideTipsyCore(opId){setTarget(null,null);if($fakeTipTarget){$fakeTipTarget.tipsy("leave")}}function hideOtherTipsies(){var hideTipsies=sharedTipsyInfo&&sharedTipsyInfo.behaviors;if(hideTipsies&&hideTipsies.length>1){hideTipsies.forEach(function(aHideTipsy){if(aHideTipsy!==hideTipsyOther){aHideTipsy()}})}}function updateTipsy(ev){if(!$fakeTipTarget){return}if(prevMouseX!=null&&Math.abs(ev.clientX-prevMouseX)<3&&Math.abs(ev.clientY-prevMouseY)<3){return}var tag=this.$scene;var scenes;if(!tag||!(scenes=tag.scenes)||!scenes.mark||(scenes.mark!==_mark)){return}var renderId=_mark.renderId();var renderIdChanged=(renderId!==_renderId);var followMouse=opts.followMouse;if(!followMouse&&!renderIdChanged){return}var opId=getNewOperationId();if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Updating opId="+opId)}prevMouseX=ev.clientX;prevMouseY=ev.clientY;var bounds;if(followMouse){bounds=getMouseBounds(ev)}if(renderIdChanged){_renderId=renderId;_mark.context(scenes,tag.index,function(){if(!followMouse){bounds=getInstanceBounds()}var text=getTooltipText();if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Update text. Was hidden. Text: "+text)}$fakeTipTarget.tipsy('setTitle',text);updateUserGravity()})}setFakeTipTargetBounds(bounds);hideOtherTipsies();$fakeTipTarget.tipsy("update")}function initBehavior(mark){if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Creating")}createTipsy(mark);if(usesPoint){mark.event('unpoint',hideTipsy)}}function showTipsy(mark){var opId=getNewOperationId();if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Show IN opId="+opId)}if(!$canvas){initBehavior(mark)}var isHidden=!$targetElem;setTarget(pv.event.target,mark);var text=getTooltipText();if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Text: "+text)}$fakeTipTarget.tipsy('setTitle',text);setFakeTipTargetBounds(opts.followMouse?getMouseBounds():getInstanceBounds());updateUserGravity();hideOtherTipsies();if(isHidden){$fakeTipTarget.tipsy('enter')}else{$fakeTipTarget.tipsy('update')}if(_tip.debug>=4){_tip.log("[TIPSY] #"+_tipsyId+" Show OUT")}}function tipsyBehavior(){var mark=this;if(!isEnabled||isEnabled(tipsyBehavior,mark)){showTipsy(mark)}}return tipsyBehavior};var _tip=pv.Behavior.tipsy;_tip.debug=0;_tip.setDebug=function(level){_tip.debug=level};_tip.log=function(m){if(typeof console!=="undefined"){console.log(''+m)}};function toParentTransform(parentPanel){return pv.Transform.identity.translate(parentPanel.left(),parentPanel.top()).times(parentPanel.transform())}function getVisibleScreenBounds(mark){var instance=mark.instance(),left=instance.left,top=instance.top,width=instance.width,height=instance.height,right,bottom,parent;while((parent=mark.parent)){if(left<0){width+=left;left=0}if(top<0){height+=top;top=0}right=instance.right;if(right<0){width+=right}bottom=instance.bottom;if(bottom<0){height+=bottom}var t=toParentTransform(parent),s=t.k;left=t.x+(s*left);top=t.y+(s*top);width=s*width;height=s*height;mark=parent;instance=mark.instance()}return{left:left,top:top,width:width,height:height}}}()); \ No newline at end of file diff --git a/pacotes/ccc2/def/def.js b/pacotes/ccc2/def/def.js deleted file mode 100755 index eadf8b0..0000000 --- a/pacotes/ccc2/def/def.js +++ /dev/null @@ -1,2704 +0,0 @@ -/** @private */ -var arraySlice = Array.prototype.slice; - -if(!Object.keys) { - /** @ignore */ - Object.keys = function(o){ - /* Object function not being used as a constructor */ - /*jshint newcap:false */ - if (o !== Object(o)){ - throw new TypeError('Object.keys called on non-object'); - } - - var ret = []; - for(var p in o){ - if(Object.prototype.hasOwnProperty.call(o,p)){ - ret.push(p); - } - } - - return ret; - }; -} - -//protovis has it -//if (!Array.prototype.filter){ -// /** @ignore */ -// Array.prototype.filter = function(fun, ctx){ -// var len = this.length >>> 0; -// if (typeof fun !== 'function'){ -// throw new TypeError(); -// } -// -// var res = []; -// for (var i = 0; i < len; i++){ -// if (i in this){ -// var val = this[i]; // in case fun mutates this -// if (fun.call(ctx, val, i, this)){ -// res.push(val); -// } -// } -// } -// -// return res; -// }; -//} - -//protovis has it -//if (!Array.prototype.forEach){ -// Array.prototype.forEach = function(fun, ctx){ -// for(var i = 0, len = this.length; i < len; ++i) { -// fun.call(ctx, this[i], i, this); -// } -// }; -//} - -if(!Object.create){ - /** @ignore */ - Object.create = (function(){ - - var Klass = function(){}, - proto = Klass.prototype; - - /** @private */ - function create(baseProto){ - Klass.prototype = baseProto || {}; - var instance = new Klass(); - Klass.prototype = proto; - - return instance; - } - - return create; - }()); -} - -if (!Function.prototype.bind) { - Function.prototype.bind = function (ctx) { - var staticArgs = arraySlice.call(arguments, 1); - var fToBind = this; - - return function (){ - return fToBind.apply(ctx, staticArgs.concat(arraySlice.call(arguments))); - }; - }; -} - -// Basic JSON shim -if(!this.JSON){ - /** @ignore */ - this.JSON = {}; -} -if(!this.JSON.stringify){ - /** @ignore */ - this.JSON.stringify = function(t){ - return '' + t; - }; -} - -// ------------------------ - -/** @private */ -var objectHasOwn = Object.prototype.hasOwnProperty; - -/** - * @name def - * @namespace The 'definition' library root namespace. - */ -var def = /** @lends def */{ - /** - * The JavaScript global object. - * @type {object} - */ - global: this, - - /** - * Gets the value of an existing, own or inherited, and not "nully", property of an object, - * or if unsatisfied, a specified default value. - * - * @param {object} [o] The object whose property value is desired. - * @param {string} p The desired property name. - * If the value is not a string, - * it is converted to one, as if String(p) were used. - * @param [dv=undefined] The default value. - * - * @returns {any} The satisfying property value or the specified default value. - * - * @see def.getOwn - * @see def.nully - */ - get: function(o, p, dv){ - var v; - return o && (v = o[p]) != null ? v : dv; - }, - - gets: function(o, props){ - return props.map(function(p){ return o[p]; }); - }, - - getPath: function(o, path, dv, create){ - if(!o) { - return dv; - } - - if(path != null){ - var parts = def.array.is(path) ? path : path.split('.'); - var L = parts.length; - if(L){ - var i = 0; - while(i < L){ - var part = parts[i++]; - var value = o[part]; - if(value == null){ - if(!create){ - return dv; - } - value = o[part] = (dv == null || isNaN(+dv)) ? {} : []; - } - - o = value; - } - } - } - - return o; - }, - - setPath: function(o, path, v){ - if(o && path != null){ - var parts = def.array.is(path) ? path : path.split('.'); - if(parts.length){ - var pLast = parts.pop(); - o = def.getPath(o, parts, pLast, true); - if(o != null){ - o[pLast] = v; - } - } - } - - return o; - }, - - /** - * Creates a property getter function, - * for a specified property name. - * - * @param {string} name The name of the property. - * @param [dv=undefined] - * The default value to return - * if the property would be accessed on null or undefined. - * @type function - */ - propGet: function(p, dv){ - p = '' + p; - - /** - * Gets the value of a prespecified property - * of a given thing. - * - * @param [o] The thing whose prespecified property is to be read. - *

- * If {@link o} is not "nully", - * but is not of type 'object', - * the function behaves equivalently to: - *

- *
-         * return Object(o)[propName];
-         * 
- * - * @returns {any} - * If the specified {@link o} is not "nully", - * returns the value of the prespecified property on it; - * otherwise, returns the prespecified default value. - * - * @private - */ - return function(o){ - return o != null ? o[p] : dv; - }; - }, - - // TODO: propSet ? - - /** - * Gets the value of an existing, own, and not "nully", property of an object, - * or if unsatisfied, a specified default value. - * - * @param {object} [o] The object whose property value is desired. - * @param {string} p The desired property name. - * If the value is not a string, - * it is converted to one, as if String(p) were used. - * @param dv The default value. - * - * @returns {any} The satisfying property value or the specified default value. - * - * @see def.get - * @see def.hasOwn - * @see def.nully - */ - getOwn: function(o, p, dv){ - var v; - return o && objectHasOwn.call(o, p) && (v = o[p]) != null ? v : dv; - }, - - hasOwn: function(o, p){ - return !!o && objectHasOwn.call(o, p); - }, - - hasOwnProp: objectHasOwn, - - set: function(o){ - if(!o) { - o = {}; - } - - var a = arguments; - for(var i = 1, A = a.length - 1 ; i < A ; i += 2) { - o[a[i]] = a[i+1]; - } - - return o; - }, - - setDefaults: function(o, o2){ - if(!o) { - o = {}; - } - - var a = arguments; - var A = a.length; - var p; - if(A === 2 && def.object.is(o2)){ - for(p in o2){ - if(o[p] == null){ - o[p] = o2[p]; - } - } - } else { - A--; - for(var i = 1 ; i < A ; i += 2) { - p = a[i]; - if(o[p] == null){ - o[p] = a[i+1]; - } - } - } - - return o; - }, - - setUDefaults: function(o, o2){ - if(!o) { - o = {}; - } - - var a = arguments; - var A = a.length; - var p; - if(A === 2 && def.object.is(o2)){ - for(p in o2){ - if(o[p] === undefined){ - o[p] = o2[p]; - } - } - } else { - A--; - for(var i = 1 ; i < A ; i += 2) { - p = a[i]; - if(o[p] === undefined){ - o[p] = a[i+1]; - } - } - } - - return o; - }, - - /** - * Calls a function - * for every own property of a specified object. - * - * @param {object} [o] The object whose own properties are traversed. - * @param {function} [fun] The function to be called once per own property of o. - * The signature of the function is: - *
-     * function(value, property : string, o : object) : any
-     * 
- * - * @param {object} [ctx=null] The context object on which to call fun. - * - * @type undefined - */ - eachOwn: function(o, fun, ctx){ - if(o){ - for(var p in o){ - if(objectHasOwn.call(o, p)){ - fun.call(ctx, o[p], p, o); - } - } - } - }, - - /** - * Calls a function - * for every property of a specified object, own or inherited. - * - * @param {object} [o] The object whose own properties are traversed. - * @param {function} [fun] The function to be called once per own property of o. - * The signature of the function is: - *
-     * function(value, property : string, o : object) : any
-     * 
- * - * @param {object} [ctx=null] The context object on which to call fun. - * - * @type undefined - */ - each: function(o, fun, ctx){ - if(o){ - for(var p in o){ - fun.call(ctx, o[p], p, o); - } - } - }, - - copyOwn: function(a, b){ - var to, from; - if(arguments.length >= 2) { - to = a || {}; - from = b; - } else { - to = {}; - from = a; - } - - if(from){ - for(var p in from){ - if(objectHasOwn.call(from, p)){ - to[p] = from[p]; - } - } - } - - return to; - }, - - copy: function(a, b){ - var to, from; - if(arguments.length >= 2) { - to = a || {}; - from = b; - } else { - to = {}; - from = a; - } - - if(from) { - for(var p in from) { - to[p] = from[p]; - } - } - - return to; - }, - - copyProps: function(a, b, props){ - var to, from; - if(arguments.length >= 3) { - to = a || {}; - from = b; - } else { - to = {}; - from = a; - props = b; - } - - if(props) { - if(from){ - props.forEach(function(p){ to[p] = from[p]; }); - } else { - props.forEach(function(p){ to[p] = undefined; }); - } - } - - return to; - }, - - keys: function(o){ - var keys = []; - for(var p in o) { - keys.push(p); - } - - return keys; - }, - - values: function(o){ - var values = []; - for(var p in o) { - values.push(o[p]); - } - - return values; - }, - - uniqueIndex: function(o, key, ctx){ - var index = {}; - - for(var p in o){ - var v = key ? key.call(ctx, o[p]) : o[p]; - if(v != null && !objectHasOwn.call(index, v)){ - index[v] = p; - } - } - - return index; - }, - - ownKeys: Object.keys, - - own: function(o, f, ctx){ - var keys = Object.keys(o); - return f ? - keys.map(function(key){ return f.call(ctx, o[key], key); }) : - keys.map(function(key){ return o[key]; }); - }, - - scope: function(scopeFun, ctx){ - return scopeFun.call(ctx); - }, - - // Special functions ---------------- - - /** - * The natural order comparator function. - * @field - * @type function - */ - compare: function(a, b){ - /* Identity is favored because, otherwise, - * comparisons like: compare(NaN, 0) would return 0... - * This isn't perfect either, because: - * compare(NaN, 0) === compare(0, NaN) === -1 - * so sorting may end in an end or the other... - */ - return (a === b) ? 0 : ((a > b) ? 1 : -1); - //return (a < b) ? -1 : ((a > b) ? 1 : 0); - }, - - compareReverse: function(a, b){ - return (a === b) ? 0 : ((a > b) ? -1 : 1); - }, - - methodCaller: function(p, context){ - if(context){ - return function(){ - return context[p].apply(context, arguments); - }; - } - - /* floating method */ - return function(){ - return this[p].apply(this, arguments); - }; - }, - - /** - * The identity function. - * @field - * @type function - */ - identity: function(x){ return x; }, - - add: function(a, b){ return a + b; }, - - // negate? - negate: function(f){ - return function(){ - return !f.apply(this, arguments); - }; - }, - - // Constant functions ---------------- - - /** - * The NO OPeration function. - * @field - * @type function - */ - noop: function noop(){ /* NOOP */ }, - - retTrue: function(){ return true; }, - retFalse: function(){ return false; }, - - // Type namespaces ---------------- - - number: { - is: function(v){ - return typeof v === 'number'; - }, - - as: function(d, dv){ - var v = parseFloat(d); - return isNaN(v) ? (dv || 0) : v; - }, - - to: function(d, dv){ - var v = parseFloat(d); - return isNaN(v) ? (dv || 0) : v; - } - }, - - array: { - - is: function(v){ - return (v instanceof Array); - }, - - isLike: function(v){ - return v && (v.length != null) && (typeof v !== 'string'); - }, - - // TODO: this should work as other 'as' methods... - /** - * Converts something to an array if it is not one already, - * and if it is not nully. - * - * @param thing A thing to convert to an array. - * @returns {Array} - */ - as: function(thing){ - return (thing instanceof Array) ? thing : ((thing != null) ? [thing] : null); - }, - - to: function(thing){ - return (thing instanceof Array) ? thing : ((thing != null) ? [thing] : null); - }, - - lazy: function(scope, p, f, ctx){ - return scope[p] || (scope[p] = (f ? f.call(ctx, p) : [])); - }, - - copy: function(al/*, start, end*/){ - return arraySlice.apply(al, arraySlice.call(arguments, 1)); - } - }, - - object: { - is: function(v){ - return v && typeof(v) === 'object'; // Is (v instanceof Object) faster? - }, - - isNative: function(v){ - // Sightly faster, but may cause boxing? - return (!!v) && /*typeof(v) === 'object' &&*/ v.constructor === Object; - }, - - as: function(v){ - return v && typeof(v) === 'object' ? v : null; - }, - - asNative: function(v){ - // Sightly faster, but may cause boxing? - return v && /*typeof(v) === 'object' &&*/ v.constructor === Object ? - v : - null; - }, - - lazy: function(scope, p, f, ctx){ - return scope[p] || - (scope[p] = (f ? f.call(ctx, p) : {})); - } - }, - - string: { - is: function(v){ - return typeof v === 'string'; - }, - - to: function(v, ds){ - return v != null ? ('' + v) : (ds || ''); - }, - - join: function(sep){ - var a = arguments; - var L = a.length; - var v, v2; - - switch(L){ - case 3: - v = a[1]; - v2 = a[2]; - if(v != null && v !== ""){ - if(v2 != null && v2 !== "") { - return (""+v) + sep + (""+v2); - } - return (""+v); - } else if(v2 != null && v2 !== "") { - return (""+v2); - } - - return ""; - - case 2: - v = a[1]; - return v != null ? (""+v) : ""; - - case 1: - case 0: return ""; - } - - // general case - - var args = []; - for(var i = 1 ; i < L ; i++){ - v = a[i]; - if(v != null && v !== ""){ - args.push("" + v); - } - } - - return args.join(sep); - } - }, - - fun: { - is: function(v){ - return typeof v === 'function'; - }, - - as: function(v){ - return typeof v === 'function' ? v : null; - }, - - to: function(v){ - return typeof v === 'function' ? v : def.fun.constant(v); - }, - - constant: function(v){ - return function(){ return v; }; - } - }, - - // nully to 'dv' - nullyTo: function(v, dv){ - return v != null ? v : dv; - }, - - between: function(v, min, max){ - return Math.max(min, Math.min(v, max)); - }, - - // Predicates ---------------- - - // === null || === undefined - nully: function(v){ - return v == null; - }, - - // !== null && !== undefined - notNully: function(v){ - return v != null; - }, - - // !== undefined - notUndef: function(v){ - return v !== undefined; - }, - - empty: function(v){ - return v == null || v === ''; - }, - - notEmpty: function(v){ - return v != null && v !== ''; - }, - - /** - * The truthy function. - * @field - * @type function - */ - truthy: function(x){ return !!x; }, - - /** - * The falsy function. - * @field - * @type function - */ - falsy: function(x){ return !x; }, - - // ----------------- - - /* Ensures the first letter is upper case */ - firstUpperCase: function(s){ - if(s) { - var c = s.charAt(0), - cU = c.toUpperCase(); - if(c !== cU) { - s = cU + s.substr(1); - } - } - return s; - }, - - firstLowerCase: function(s){ - if(s) { - var c = s.charAt(0), - cL = c.toLowerCase(); - if(c !== cL) { - s = cL + s.substr(1); - } - } - return s; - }, - - /** - * Formats a string by replacing - * place-holder markers, of the form "{foo}", - * with the value of corresponding properties - * of the specified scope argument. - * - * @param {string} mask The string to format. - * @param {object|function} [scope] The scope object or function. - * @param {object} [ctx] The context object for a scope function. - * - * @example - *
-     * def.format("The name '{0}' is undefined.", ['foo']);
-     * // == "The name 'foo' is undefined."
-     * 
-     * def.format("The name '{foo}' is undefined, and so is '{what}'.", {foo: 'bar'});
-     * // == "The name 'bar' is undefined, and so is ''."
-     * 
-     * def.format("The name '{{foo}}' is undefined.", {foo: 'bar'});
-     * // == "The name '{{foo}}' is undefined."
-     * 
- * - * @returns {string} The formatted string. - */ - format: function(mask, scope, ctx){ - if(mask == null || mask === '') { - return ""; - } - - var isScopeFun = scope && def.fun.is(scope); - - return mask.replace(/(^|[^{])\{([^{}]+)\}/g, function($0, before, prop){ - var value; - if(scope){ - if(isScopeFun){ - value = scope.call(ctx, prop); - } else { - value = scope[prop]; - } - } else { - value = null; - } - - // NOTE: calls .toString() of value as a side effect of the + operator - return before + (value == null ? "" : value); - }); - }, - - // -------------- - - /** - * Binds a list of types with the specified values, by position. - *

- * A null value is bound to any type. - *

- *

- * When a value is of a different type than the type desired at a given position - * the position is bound to undefined and - * the unbound value is passed to the next position. - *

- * - * @returns {any[]} An array representing the binding, with the values bound to each type. - */ - destructuringTypeBind: function(types, values){ - var T = types.length; - var result = new Array(T); - if(T && values){ - var V = values.length; - if(V){ - var v = 0; - var t = 0; - do{ - var value = values[v]; - - // any type matches null - if(value == null || typeof value === types[t]){ - // bind value to type - result[t] = value; - v++; - } - t++; - }while(t < T && v < V); - } - } - - return result; - }, - - // -------------- - - error: function(error){ - return (error instanceof Error) ? error : new Error(error); - }, - - fail: function(error){ - throw def.error(error); - }, - - assert: function(msg, scope){ - throw def.error.assertionFailed(msg, scope); - } -}; - -def.lazy = def.object.lazy; - -// Adapted from -// http://www.codeproject.com/Articles/133118/Safe-Factory-Pattern-Private-instance-state-in-Jav/ -def.shared = function(){ - var _channel = null; - - /** @private */ - function create(value){ - - /** @private */ - function safe(){ - _channel = value; - } - - return safe; - } - - /** @private */ - function opener(safe){ - if(_channel != null){ throw new Error("Access denied."); } - - safe(); - - var value; - value = _channel; - _channel = null; - return value; - } - - opener.safe = create; - - return opener; -}; - -var errors = { - operationInvalid: function(msg, scope){ - return def.error(def.string.join(" ", "Invalid operation.", def.format(msg, scope))); - }, - - notImplemented: function(){ - return def.error("Not implemented."); - }, - - argumentRequired: function(name){ - return def.error(def.format("Required argument '{0}'.", [name])); - }, - - argumentInvalid: function(name, msg, scope){ - return def.error( - def.string.join(" ", - def.format("Invalid argument '{0}'.", [name]), - def.format(msg, scope))); - }, - - assertionFailed: function(msg, scope){ - return def.error( - def.string.join(" ", - "Assertion failed.", - def.format(msg, scope))); - } -}; - -def.copyOwn(def.error, errors); - -/* Create direct fail versions of errors */ -def.eachOwn(errors, function(errorFun, name){ - def.fail[name] = function(){ - throw errorFun.apply(null, arguments); - }; -}); - -// ----------------------- - -/** @private */ -var currentNamespace = def, // at the end of the file it is set to def.global - globalNamespaces = {}, // registered global namespaces by name: globalName -> object - namespaceStack = []; - -/** @private */ -function globalSpace(name, space){ - return globalNamespaces[name] = space; -} - -/** @private */ -function getNamespace(name, base){ - var current = base || currentNamespace; - if(name){ - var parts = name.split('.'); - var L = parts.length; - if(L){ - var i = 0; - var part; - if(current === def.global){ - part = parts[0]; - var globalNamespace = def.getOwn(globalNamespaces, part); - if(globalNamespace){ - current = globalNamespace; - i++; - } - } - - while(i < L){ - part = parts[i++]; - current = current[part] || (current[part] = {}); - } - } - } - - return current; -} - -/** - * Ensures a namespace exists given its name and, optionally, its base namespace. - * If a definition function is specified, - * it is executed having the namespace as current namespace. - * - * @param {string} name The namespace name. - * @param {object} [base] The base namespace object. - * @param {function} [definition] The namespace definition function. - * @type object - * - * @private - */ -function createSpace(name, base, definition){ - if(def.fun.is(base)){ - definition = base; - base = null; - } - - var namespace = getNamespace(name, base); - - if(definition){ - namespaceStack.push(currentNamespace); - try{ - definition(namespace); - } finally { - currentNamespace = namespaceStack.pop(); - } - } - - return namespace; -} - -/** @private */ -function defineName(namespace, name, value){ - /*jshint expr:true */ - !def.hasOwn(namespace, name) || - def.fail.operationInvalid("Name '{0}' is already defined in namespace.", [name]); - - return namespace[name] = value; -} - -/** - * Defines a relative namespace with - * name name on the current namespace. - * - *

- * Namespace declarations may be nested. - *

- *

- * The current namespace can be obtained by - * calling {@link def.space} with no arguments. - * The current namespace affects other nested declarations, such as {@link def.type}. - *

- *

- * A composite namespace name contains dots, ".", separating its elements. - *

- * @example - *
- * def.space('foo.bar', function(space){
- *     space.hello = 1;
- * });
- * 
- * - * @function - * - * @param {String} name The name of the namespace to obtain. - * If nully, the current namespace is implied. - * - * @param {Function} definition - * A function that is called whith the desired namespace - * as first argument and while it is current. - * - * @returns {object} The namespace. - */ -def.space = createSpace; - -/** - * Registers a name and an object as a global namespace. - * @param {string} name The name of the global namespace component to register. - * @param {object} space The object that represents the namespace. - * @returns {object} the registered namespace object. - */ -def.globalSpace = globalSpace; - -// ----------------------- - -def.mixin = createMixin(Object.create); -def.copyOwn(def.mixin, { - custom: createMixin, - inherit: def.mixin, - copy: createMixin(def.copy), - share: createMixin(def.identity) -}); - -/** @private */ -function createMixin(protectNativeObject){ - return function(instance/*mixin1, mixin2, ...*/){ - return mixinMany(instance, arraySlice.call(arguments, 1), protectNativeObject); - }; -} - -/** @private */ -function mixinMany(instance, mixins, protectNativeObject){ - for(var i = 0, L = mixins.length ; i < L ; i++){ - var mixin = mixins[i]; - if(mixin){ - mixin = def.object.as(mixin.prototype || mixin); - if(mixin){ - mixinRecursive(instance, mixin, protectNativeObject); - } - } - } - - return instance; -} - -/** @private */ -function mixinRecursive(instance, mixin, protectNativeObject){ - for(var p in mixin){ - mixinProp(instance, p, mixin[p], protectNativeObject); - } -} - -/** @private */ -function mixinProp(instance, p, vMixin, protectNativeObject){ - if(vMixin !== undefined){ - var oMixin, - oTo = def.object.asNative(instance[p]); - - if(oTo){ - oMixin = def.object.as(vMixin); - if(oMixin){ - // If oTo is inherited, don't change it - // Inherit from it and assign it locally. - // It will be the target of the mixin. - if(!objectHasOwn.call(instance, p)){ - instance[p] = oTo = Object.create(oTo); - } - - // Mixin the two objects - mixinRecursive(oTo, oMixin, protectNativeObject); - } else { - // Overwrite oTo with a simple value - instance[p] = vMixin; - } - } else { - // Target property does not contain a native object. - oMixin = def.object.asNative(vMixin); - if(oMixin){ - // Should vMixin be set directly in instance[p] ? - // Should we copy its properties into a fresh object ? - // Should we inherit from it ? - vMixin = (protectNativeObject || Object.create)(oMixin); - } - - instance[p] = vMixin; - } - } -} - -// ----------------------- - -/** @private */ -function createRecursive(instance){ - for(var p in instance){ - var vObj = def.object.asNative(instance[p]); - if(vObj){ - createRecursive( (instance[p] = Object.create(vObj)) ); - } - } -} - -// Creates an object whose prototype is the specified object. -def.create = function(/* [deep, ] baseProto, mixin1, mixin2, ...*/){ - var mixins = arraySlice.call(arguments), - deep = true, - baseProto = mixins.shift(); - - if(typeof(baseProto) === 'boolean'){ - deep = baseProto; - baseProto = mixins.shift(); - } - - var instance = baseProto ? Object.create(baseProto) : {}; - if(deep){ - createRecursive(instance); - } - - // NOTE: - if(mixins.length > 0){ - mixins.unshift(instance); - def.mixin.apply(def, mixins); - } - - return instance; -}; - -// ----------------------- - -def.scope(function(){ - var shared = def.shared(); - - /** @private */ - function typeLocked(){ - return def.error.operationInvalid("Type is locked."); - } - - /** @ignore */ - var typeProto = /** lends def.type# */{ - init: function(init){ - /*jshint expr:true */ - - init || def.fail.argumentRequired('init'); - - var state = shared(this.safe); - - !state.locked || def.fail(typeLocked()); - - // NOTE: access to init inherits baseState's init! - // Before calling init or postInit, baseState.initOrPost is inherited as well. - var baseInit = state.init; - if(baseInit){ - init = override(init, baseInit); - } - - state.init = init; - state.initOrPost = true; - - return this; - }, - - postInit: function(postInit){ - /*jshint expr:true */ - - postInit || def.fail.argumentRequired('postInit'); - - var state = shared(this.safe); - - !state.locked || def.fail(typeLocked()); - - // NOTE: access to post inherits baseState's post! - // Before calling init or postInit, baseState.initOrPost is inherited as well. - var basePostInit = state.post; - if(basePostInit){ - postInit = override(postInit, basePostInit); - } - - state.post = postInit; - state.initOrPost = true; - - return this; - }, - - add: function(mixin){ - var state = shared(this.safe); - - /*jshint expr:true */ - !state.locked || def.fail(typeLocked()); - - var proto = this.prototype; - var baseState = state.base; - - def.each(mixin.prototype || mixin, function(value, p){ - // filter props/methods - switch(p){ - case 'base': - case 'constructor': // don't let overwrite 'constructor' of prototype - return; - - case 'toString': - if(value === toStringMethod){ - return; - } - break; - - case 'override': - if(value === overrideMethod){ - return; - } - break; - } - - if(value){ - // Try to convert to method - var method = asMethod(value); - if(method) { - var baseMethod; - - // Check if it is an override - - // Exclude inherited stuff from Object.prototype - var bm = state.methods[p]; - if(bm && (bm instanceof Method)){ - baseMethod = bm; - } else if(baseState) { - bm = baseState.methods[p]; - if(bm && (bm instanceof Method)){ - baseMethod = bm; - } - } - - state.methods[p] = method; - - if(baseMethod){ - // Replace value with an override function - // that intercepts the call and sets the correct - // 'base' property before calling the original value function - value = baseMethod.override(method); - } - - proto[p] = value; - return; - } - } - - mixinProp(proto, p, value, /*protectNativeValue*/def.identity); // Can use native object value directly - }); - - return this; - }, - - getStatic: function(p){ - return getStatic(shared(this.safe), p); - }, - - addStatic: function(mixin){ - var state = shared(this.safe); - - /*jshint expr:true */ - !state.locked || def.fail(typeLocked()); - - for(var p in mixin){ - if(p !== 'prototype'){ - var v1 = def.getOwn(this, p); - - var v2 = mixin[p]; - var o2 = def.object.as(v2); - if(o2){ - var v1Local = (v1 !== undefined); - if(!v1Local){ - v1 = getStatic(state.base, p); - } - - var o1 = def.object.asNative(v1); - if(o1){ - if(v1Local){ - def.mixin(v1, v2); - continue; - } - - v2 = def.create(v1, v2); // Extend from v1 and mixin v2 - } - } // else v2 smashes anything in this[p] - - this[p] = v2; - } - } - - return this; - } - }; - - function getStatic(state, p){ - if(state){ - do{ - var v = def.getOwn(state.constructor, p); - if(v !== undefined){ - return v; - } - } while((state = state.base)); - } - } - - // TODO: improve this code with indexOf - function TypeName(full){ - var parts; - if(full){ - if(full instanceof Array){ - parts = full; - full = parts.join('.'); - } else { - parts = full.split('.'); - } - } - - if(parts && parts.length > 1){ - this.name = parts.pop(); - this.namespace = parts.join('.'); - this.namespaceParts = parts; - } else { - this.name = full || null; - this.namespace = null; - this.namespaceParts = []; - } - } - - TypeName.prototype.toString = function(){ - return def.string.join('.', this.namespace + '.' + this.name); - }; - - function Method(spec) { - this.fun = spec.as; - if(spec) { - if(spec.isAbstract) { - this.isAbstract = true; - } - } - } - - def.copyOwn(Method.prototype, { - isAbstract: false, - override: function(method){ - // *this* is the base method - if(this.isAbstract) { - // Abstract base methods do not maintain 'base' property. - // Interception is not needed. - return method.fun; - } - - var fun2 = override(method.fun, this.fun); - // replacing the original function with the wrapper function - // makes sure that multiple (> 1) overrides work - method.fun = fun2; - - return fun2; - } - }); - - /** @private */ - function asMethod(fun) { - if(fun) { - if(def.fun.is(fun)) { - return new Method({as: fun}); - } - - if(fun instanceof Method) { - return fun; - } - - if(def.fun.is(fun.as)) { - return new Method(fun); - } - - if(fun.isAbstract) { - return new Method({isAbstract: true, as: def.fail.notImplemented }); - } - } - - return null; - } - - /** @private */ - function method(fun) { - return asMethod(fun) || def.fail.argumentInvalid('fun'); - } - - // ----------------- - - function rootType(){ - } - - var rootProto = rootType.prototype; - // Unfortunately, creates an enumerable property in every instance - rootProto.base = undefined; - - var rootState = { - locked: true, - init: undefined, - postInit: undefined, - initOrPost: false, - methods: {}, - constructor: rootType - }; - - rootType.safe = shared.safe(rootState); - - // ----------------- - - /** @private */ - function override(method, base){ - - return function(){ - var prevBase = rootProto.base; - rootProto.base = base; - try{ - return method.apply(this, arguments); - } finally { - rootProto.base = prevBase; - } - }; - } - - function overrideMethod(mname, method){ - this[mname] = override(method, this[mname]); - return this; - } - - function toStringMethod(){ - return ''+this.constructor; - } - - // ----------------- - - /** @private */ - function inherits(type, base){ - // Inherit - var proto = type.prototype = Object.create(base.prototype); - // Unfortunately, creates an enumerable property in every instance - proto.constructor = type; - - return proto; - } - - // ----------------- - - /** @private */ - function createConstructor(state){ - -// function constructor(){ -// /*jshint expr:true */ -// var method; -// if(state.initOrPost){ -// (method = state.init) && method.apply(this, arguments); -// (method = state.post) && method.apply(this, arguments); -// } -// } - - // Slightly faster version -// var init, post; -// var start = function(){ -// start = null; -// if(state.initOrPost){ -// init = state.init; -// post = state.post; -// } -// }; -// -// function constructor(){ -// /*jshint expr:true */ -// start && start(); -// -// init && init.apply(this, arguments); -// post && post.apply(this, arguments); -// } - - // Even faster, still - var S = 1; - var steps = [ - // Start up class step - function(){ - S = 0; - if(state.initOrPost){ - steps.length = 0; - if(state.init){ - steps.push(state.init); - S++; - } - - if(state.post){ - steps.push(state.post); - S++; - } - - // Call constructor recursively - constructor.apply(this, arguments); - - return false; // stop initial constructor from running postInit again... - } else { - steps = null; - } - } - ]; - - function constructor(){ - if(S){ - var i = 0; - while(steps[i].apply(this, arguments) !== false && ++i < S){} - } - } - - return constructor; - } - - /** @private The type of the arguments of the {@link def.type} function. */ - var _typeFunArgTypes = ['string', 'function', 'object']; - - /** - * Constructs a type with the specified name in the current namespace. - * - * @param {string} [name] The new type name, relative to the base argument. - * When unspecified, an anonymous type is created. - * The type is not published in any namespace. - * - * @param {object} [baseType] The base type. - * @param {object} [space] The namespace where to define a named type. - * The default namespace is the current namespace. - */ - function type(/* name[, baseType[, space]] | baseType[, space] | space */){ - - var args = def.destructuringTypeBind(_typeFunArgTypes, arguments); - - return typeCore.apply(this, args); - } - - function typeCore(name, baseType, space){ - var typeName = new TypeName(name); - - // --------------- - - var baseState; - if(baseType){ - baseState = (baseType.safe && shared(baseType.safe)) || - def.fail.operationInvalid("Invalid \"foreign\" base type."); - baseState.locked = true; - } else { - baseType = rootType; - baseState = rootState; - } - - // --------------- - - var state = Object.create(baseState); - state.locked = false; - state.base = baseState; - state.methods = Object.create(baseState.methods); - - // --------------- - - var constructor = createConstructor(state); - - def.copyOwn(constructor, typeProto); - - constructor.name = typeName.name; - constructor.typeName = typeName; - constructor.safe = shared.safe(state); - constructor.toString = function(){ return (''+this.typeName) || "Anonymous type"; }; - - var proto = inherits(constructor, baseType); - - state.constructor = constructor; - - // --------------- - // Default methods (can be overwritten with Type#add) - - proto.override = overrideMethod; - proto.toString = toStringMethod; - - // --------------- - - if(typeName.name){ - defineName(def.space(typeName.namespace, space), - typeName.name, - constructor); - } - - return constructor; - } - - def.type = type; - def.method = method; -}); - -// ---------------------- - -def.copyOwn(def.array, /** @lends def.array */{ - /** - * Creates an array of the specified length, - * and, optionally, initializes it with the specified default value. - */ - create: function(len, dv){ - var a = len >= 0 ? new Array(len) : []; - if(dv !== undefined){ - for(var i = 0 ; i < len ; i++){ - a[i] = dv; - } - } - - return a; - }, - - append: function(target, source, start){ - if(start == null){ - start = 0; - } - - for(var i = 0, L = source.length, T = target.length ; i < L ; i++){ - target[T + i] = source[start + i]; - } - - return target; - }, - - appendMany: function(target){ - var a = arguments; - var S = a.length; - if(S > 1){ - var t = target.length; - for(var s = 1 ; s < S ; s++){ - var source = a[s]; - if(source){ - var i = 0; - var L = source.length; - while(i < L){ - target[t++] = source[i++]; - } - } - } - } - - return target; - }, - - prepend: function(target, source, start){ - if(start == null){ - start = 0; - } - - for(var i = 0, L = source.length ; i < L ; i++){ - target.unshift(source[start + i]); - } - - return target; - }, - - removeAt: function(array, index){ - return array.splice(index, 1)[0]; - }, - - insertAt: function(array, index, elem){ - array.splice(index, 0, elem); - return array; - }, - - binarySearch: function(array, item, comparer, key){ - if(!comparer) { comparer = def.compare; } - - var low = 0, high = array.length - 1; - while(low <= high) { - var mid = (low + high) >> 1; // <=> Math.floor((l+h) / 2) - - var result = comparer(item, key ? key(array[mid]) : array[mid]); - if (result < 0) { - high = mid - 1; - } else if (result > 0) { - low = mid + 1; - } else { - return mid; - } - } - - /* Item was not found but would be inserted at ~low */ - return ~low; // two's complement <=> -low - 1 - }, - - /** - * Inserts an item in an array, - * previously sorted with a specified comparer, - * if the item is not already contained in it. - * - * @param {Array} array A sorted array. - * @param item An item to insert in the array. - * @param {Function} [comparer] A comparer function. - * - * @returns {Number} - * If the item is already contained in the array returns its index. - * If the item was not contained in the array returns the two's complement - * of the index where the item was inserted. - */ - insert: function(array, item, comparer){ - - var index = def.array.binarySearch(array, item, comparer); - if(index < 0){ - // Insert at the two's complement of index - array.splice(~index, 0, item); - } - - return index; - }, - - remove: function(array, item, comparer){ - var index = def.array.binarySearch(array, item, comparer); - if(index >= 0) { - return array.splice(index, 1)[0]; - } - // return undefined; - } -}); - -// ----------------- - -var nextGlobalId = 1, - nextIdByScope = {}; -def.nextId = function(scope){ - if(scope) { - var nextId = def.getOwn(nextIdByScope, scope) || 1; - nextIdByScope[scope] = nextId + 1; - return nextId; - } - - return nextGlobalId++; -}; - -// -------------------- - -def.type('Set') -.init(function(source, count){ - this.source = source || {}; - this.count = source ? (count != null ? count : def.ownKeys(source).length) : 0; -}) -.add({ - has: function(p){ - return objectHasOwn.call(this.source, p); - }, - - add: function(p){ - var source = this.source; - if(!objectHasOwn.call(source, p)) { - this.count++; - source[p] = true; - } - - return this; - }, - - rem: function(p){ - if(objectHasOwn.call(this.source, p)) { - delete this.source[p]; - this.count--; - } - - return this; - }, - - clear: function(){ - if(this.count) { - this.source = {}; - this.count = 0; - } - return this; - }, - - members: function(){ - return def.ownKeys(this.source); - } -}); - -// --------------- - -def.type('Map') -.init(function(source, count){ - this.source = source || {}; - this.count = source ? (count != null ? count : def.ownKeys(source).length) : 0; -}) -.add({ - has: function(p){ - return objectHasOwn.call(this.source, p); - }, - - get: function(p){ - return objectHasOwn.call(this.source, p) ? - this.source[p] : - undefined; - }, - - set: function(p, v){ - var source = this.source; - if(!objectHasOwn.call(source, p)) { - this.count++; - } - - source[p] = v; - return this; - }, - - rem: function(p){ - if(objectHasOwn.call(this.source, p)) { - delete this.source[p]; - this.count--; - } - - return this; - }, - - clear: function(){ - if(this.count) { - this.source = {}; - this.count = 0; - } - return this; - }, - - copy: function(other){ - // Add other to this one - def.eachOwn(other.source, function(value, p){ - this.set(p, value); - }, this); - }, - - values: function(){ - return def.own(this.source); - }, - - keys: function(){ - return def.ownKeys(this.source); - }, - - clone: function(){ - return new def.Map(def.copy(this.source), this.count); - }, - - /** - * The union of the current map with the specified - * map minus their intersection. - * - * (A U B) \ (A /\ B) - * (A \ B) U (B \ A) - * @param {def.Map} other The map with which to perform the operation. - * @type {def.Map} - */ - symmetricDifference: function(other){ - if(!this.count){ - return other.clone(); - } - if(!other.count){ - return this.clone(); - } - - var result = {}; - var count = 0; - - var as = this.source; - var bs = other.source; - - def.eachOwn(as, function(a, p){ - if(!objectHasOwn.call(bs, p)){ - result[p] = a; - count++; - } - }); - - def.eachOwn(bs, function(b, p){ - if(!objectHasOwn.call(as, p)){ - result[p] = b; - count++; - } - }); - - return new def.Map(result, count); - }, - - intersect: function(other, result){ - if(!result){ - result = new def.Map(); - } - - def.eachOwn(this.source, function(value, p){ - if(other.has(p)) { - result.set(p, value); - } - }); - - return result; - } -}); - -// -------------------- - -//--------------- - -def.type('OrderedMap') -.init(function(){ - this._list = []; - this._map = {}; -}) -.add({ - has: function(key){ - return objectHasOwn.call(this._map, key); - }, - - count: function(){ - return this._list.length; - }, - - get: function(key){ - var bucket = def.getOwn(this._map, key); - if(bucket) { - return bucket.value; - } - }, - - at: function(index){ - var bucket = this._list[index]; - if(bucket){ - return bucket.value; - } - }, - - add: function(key, v, index){ - var map = this._map; - var bucket = def.getOwn(map, key); - if(!bucket){ - bucket = map[key] = { - key: key, - value: v - }; - - if(index == null){ - this._list.push(bucket); - } else { - def.array.insertAt(this._list, index, bucket); - } - } else if(bucket.value !== v){ - bucket.value = v; - } - - return this; - }, - - rem: function(key){ - var bucket = def.getOwn(this._map, key); - if(bucket){ - // Find it - var index = this._list.indexOf(bucket); - this._list.splice(index, 1); - delete this._map[key]; - } - - return this; - }, - - clear: function(){ - if(this._list.length) { - this._map = {}; - this._list.length = 0; - } - - return this; - }, - - keys: function(){ - return def.ownKeys(this._map); - }, - - forEach: function(fun, ctx){ - return this._list.forEach(function(bucket){ - fun.call(ctx, bucket.value, bucket.key); - }); - } -}); - -// -------------------- - -def.html = { - // TODO: lousy multipass implementation! - escape: function(str){ - return def - .string.to(str) - .replace(/&/gm, "&") - .replace(//gm, ">") - .replace(/"/gm, """); - } -}; - -// -------------------- - -def.type('Query') -.init(function(){ - this.index = -1; - this.item = undefined; -}) -.add({ - next: function(){ - var index = this.index; - // already was finished - if(index === -2){ - return false; - } - - index++; - if(!this._next(index)){ - this.index = -2; - this.item = undefined; - return false; - } - - this.index = index; - return true; - }, - - /** - * @name _next - * @function - * @param {number} nextIndex The index of the next item, if one exists. - * @member def.Query# - * @returns {boolean} truthy if there is a next item, falsy otherwise. - */ - _next: def.method({isAbstract: true}), - - _finish: function(){ - this.index = -2; - this.item = undefined; - }, - - // ------------ - - each: function(fun, ctx){ - while(this.next()){ - if(fun.call(ctx, this.item, this.index) === false) { - return true; - } - } - - return false; - }, - - array: function(){ - var array = []; - while(this.next()){ - array.push(this.item); - } - return array; - }, - - sort: function(compare, by){ - if(!compare){ - compare = def.compare; - } - - if(by){ - var keyCompare = compare; - compare = function(a, b){ - return keyCompare(by(a), by(b)); - }; - } - - var sorted = this.array().sort(compare); - - return new def.ArrayLikeQuery(sorted); - }, - - /** - * Consumes the query and fills an object - * with its items. - *

- * A property is created per item in the query. - * The default name of each property is the string value of the item. - * The default value of the property is the item itself. - *

- *

- * In the case where two items have the same key, - * the last one overwrites the first. - *

- * - * @param {object} [keyArgs] Keyword arguments. - * @param {function} [keyArgs.value] A function that computes the value of each property. - * @param {function} [keyArgs.name] A function that computes the name of each property. - * @param {object} [keyArgs.context] The context object on which keyArgs.name and keyArgs.value - * are called. - * @param {object} [keyArgs.target] The object that is to receive the properties, - * instead of a new one being creating. - * - * @returns {object} A newly created object, or the specified keyArgs.target object, - * filled with properties. - */ - object: function(keyArgs){ - var target = def.get(keyArgs, 'target') || {}, - nameFun = def.get(keyArgs, 'name' ), - valueFun = def.get(keyArgs, 'value'), - ctx = def.get(keyArgs, 'context'); - - while(this.next()){ - var name = '' + (nameFun ? nameFun.call(ctx, this.item, this.index) : this.item); - target[name] = valueFun ? valueFun.call(ctx, this.item, this.index) : this.item; - } - - return target; - }, - - reduce: function(accumulator/*, [initialValue]*/){ - var i = 0, - result; - - if(arguments.length < 2) { - if(!this.next()) { - throw new TypeError("Length is 0 and no second argument"); - } - - result = this.item; - } else { - result = arguments[1]; - } - - while(this.next()) { - result = accumulator(result, this.item, this.index); - - ++i; - } - - return result; - }, - - /** - * Consumes the query and obtains the number of items. - * - * @type number - */ - count: function(){ - var count = 0; - - while(this.next()){ count++; } - - return count; - }, - - /** - * Returns the first item that satisfies a specified predicate. - *

- * If no predicate is specified, the first item is returned. - *

- * - * @param {function} [pred] A predicate to apply to every item. - * @param {any} [ctx] The context object on which to call pred. - * @param {any} [dv=undefined] The value returned in case no item exists or satisfies the predicate. - * - * @type any - */ - first: function(pred, ctx, dv){ - while(this.next()){ - if(!pred || pred.call(ctx, this.item, this.index)) { - var item = this.item; - this._finish(); - return item; - } - } - - return dv; - }, - - /** - * Returns the last item that satisfies a specified predicate. - *

- * If no predicate is specified, the last item is returned. - *

- * - * @param {function} [pred] A predicate to apply to every item. - * @param {any} [ctx] The context object on which to call pred. - * @param {any} [dv=undefined] The value returned in case no item exists or satisfies the predicate. - * - * @type any - */ - last: function(pred, ctx, dv){ - var theItem = dv; - while(this.next()){ - if(!pred || pred.call(ctx, this.item, this.index)) { - theItem = this.item; - } - } - - return theItem; - }, - - /** - * Returns true if there is at least one item satisfying a specified predicate. - *

- * If no predicate is specified, returns true if there is at least one item. - *

- * - * @param {function} [pred] A predicate to apply to every item. - * @param {any} [ctx] The context object on which to call pred. - * - * @type boolean - */ - any: function(pred, ctx){ - while(this.next()){ - if(!pred || pred.call(ctx, this.item, this.index)) { - this._finish(); - return true; - } - } - - return false; - }, - - /** - * Returns true if all the query items satisfy the specified predicate. - * @param {function} pred A predicate to apply to every item. - * @param {any} [ctx] The context object on which to call pred. - * - * @type boolean - */ - all: function(pred, ctx){ - while(this.next()){ - if(!pred.call(ctx, this.item, this.index)) { - this._finish(); - return false; - } - } - - return true; - }, - - min: function(){ - var min = null; - while(this.next()){ - if(min === null || this.item < min) { - min = this.item; - } - } - - return min; - }, - - max: function(){ - var max = null; - while(this.next()){ - if(max === null || this.item > max) { - max = this.item; - } - } - - return max; - }, - - range: function(){ - var min = null, - max = null; - - while(this.next()){ - var item = this.item; - if(min === null) { - min = max = item; - } else { - if(item < min) { - min = item; - } - if(item > max) { - max = item; - } - } - } - - return min != null ? {min: min, max: max} : null; - }, - - multipleIndex: function(keyFun, ctx){ - var keyIndex = {}; - - this.each(function(item){ - var key = keyFun ? keyFun.call(ctx, item) : item; - if(key != null) { - var sameKeyItems = def.getOwn(keyIndex, key) || (keyIndex[key] = []); - - sameKeyItems.push(item); - } - }); - - return keyIndex; - }, - - uniqueIndex: function(keyFun, ctx){ - var keyIndex = {}; - - this.each(function(item){ - var key = keyFun ? keyFun.call(ctx, item) : item; - if(key != null && !def.hasOwn(keyIndex, key)) { - keyIndex[key] = item; - } - }); - - return keyIndex; - }, - - // --------------- - // Query -> Query - - // deferred map - select: function(fun, ctx){ - return new def.SelectQuery(this, fun, ctx); - }, - - selectMany: function(fun, ctx){ - return new def.SelectManyQuery(this, fun, ctx); - }, - - union: function(/*others*/){ - var queries = def.array.append([this], arguments); - return new def.SelectManyQuery(new def.ArrayLikeQuery(queries)); - }, - - // deferred filter - where: function(fun, ctx){ - return new def.WhereQuery(this, fun, ctx); - }, - - distinct: function(fun, ctx){ - return new def.DistinctQuery(this, fun, ctx); - }, - - skip: function(n){ - return new def.SkipQuery(this, n); - }, - - take: function(n){ - if(n <= 0){ - return new def.NullQuery(); - } - - if(!isFinite(n)){ - return this; // all - } - - return new def.TakeQuery(this, n); - }, - - whayl: function(pred, ctx){ - return new def.WhileQuery(this, pred, ctx); - }, - - reverse: function(){ - return new def.ReverseQuery(this); - } -}); - -def.type('NullQuery', def.Query) -.add({ - _next: function(/*nextIndex*/){} -}); - -def.type('AdhocQuery', def.Query) -.init(function(next){ - this.base(); - this._next = next; -}); - -def.type('ArrayLikeQuery', def.Query) -.init(function(list){ - this.base(); - this._list = def.array.isLike(list) ? list : [list]; - this._count = this._list.length; -}) -.add({ - _next: function(nextIndex){ - var count = this._count; - if(nextIndex < count){ - var list = this._list; - - while(!objectHasOwn.call(list, nextIndex)){ - nextIndex++; - if(nextIndex >= count){ - return 0; - } - this._count--; - } - - this.item = list[nextIndex]; - return 1; - } - }, - - /** - * Obtains the number of items of a query. - * - * This is a more efficient implementation for the array-like class. - * @type number - */ - count: function(){ - // Count counts remaining items - var remaining = this._count; - if(this.index >= 0){ - remaining -= (this.index + 1); - } - - // Count consumes all remaining items - this._finish(); - - return remaining; - } -}); - -def.type('RangeQuery', def.Query) -.init(function(start, count, step){ - this.base(); - this._index = start; - this._count = count; // may be infinte - this._step = step == null ? 1 : step; -}) -.add({ - _next: function(nextIndex){ - if(nextIndex < this._count){ - this.item = this._index; - this._index += this._step; - return 1; - } - }, - - /** - * Obtains the number of items of a query. - * This is a more efficient implementation. - * @type number - */ - count: function(){ - // Count counts remaining items - var remaining = this._count; - if(this.index >= 0){ - remaining -= (this.index + 1); - } - - // Count consumes all remaining items - this._finish(); - - return remaining; - } -}); - -def.type('WhereQuery', def.Query) -.init(function(source, where, ctx){ - this.base(); - this._where = where; - this._ctx = ctx; - this._source = source; -}) -.add({ - _next: function(nextIndex){ - var source = this._source; - while(source.next()){ - var nextItem = source.item; - if(this._where.call(this._ctx, nextItem, source.index)){ - this.item = nextItem; - return 1; - } - } - } -}); - -def.type('WhileQuery', def.Query) -.init(function(source, pred, ctx){ - this.base(); - this._pred = pred; - this._ctx = ctx; - this._source = source; -}) -.add({ - _next: function(nextIndex){ - while(this._source.next()){ - var nextItem = this._source.item; - if(this._pred.call(this._ctx, nextItem, this._source.index)){ - this.item = nextItem; - return 1; - } - return 0; - } - } -}); - -def.type('SelectQuery', def.Query) -.init(function(source, select, ctx){ - this.base(); - this._select = select; - this._ctx = ctx; - this._source = source; -}) -.add({ - _next: function(nextIndex){ - if(this._source.next()){ - this.item = this._select.call(this._ctx, this._source.item, this._source.index); - return 1; - } - } -}); - -def.type('SelectManyQuery', def.Query) -.init(function(source, selectMany, ctx){ - this.base(); - this._selectMany = selectMany; - this._ctx = ctx; - this._source = source; - this._manySource = null; -}) -.add({ - _next: function(nextIndex){ - while(true){ - // Consume all of existing manySource - if(this._manySource){ - if(this._manySource.next()){ - this.item = this._manySource.item; - return 1; - } - - this._manySource = null; - } - - if(!query_nextMany.call(this)){ - break; - } - } - } -}); - -function query_nextMany(){ - while(this._source.next()){ - var manySource = this._selectMany ? - this._selectMany.call(this._ctx, this._source.item, this._source.index) : - this._source.item; - if(manySource != null){ - this._manySource = def.query(manySource); - return 1; - } - } -} - -def.type('DistinctQuery', def.Query) -.init(function(source, key, ctx){ - this.base(); - this._key = key; - this._ctx = ctx; - this._source = source; - this._keys = {}; -}) -.add({ - _next: function(nextIndex){ - while(this._source.next()){ - var nextItem = this._source.item, - keyValue = this._key ? - this._key.call(this._ctx, nextItem, this._source.index) : - nextItem; - - // items with null keys are ignored! - if(keyValue != null && !def.hasOwn(this._keys, keyValue)){ - this._keys[keyValue] = true; - this.item = nextItem; - return 1; - } - } - } -}); - -def.type('SkipQuery', def.Query) -.init(function(source, skip){ - this.base(); - this._source = source; - this._skip = skip; -}) -.add({ - _next: function(nextIndex){ - while(this._source.next()){ - if(this._skip > 0){ - this._skip--; - } else { - this.item = this._source.item; - return 1; - } - } - } -}); - -def.type('TakeQuery', def.Query) -.init(function(source, take){ - this.base(); - this._source = source; - this._take = take; -}) -.add({ - _next: function(nextIndex){ - if(this._take > 0 && this._source.next()){ - this._take--; - this.item = this._source.item; - return 1; - } - } -}); - -def.type('ReverseQuery', def.Query) -.init(function(source){ - this.base(); - this._source = source; -}) -.add({ - _next: function(nextIndex){ - if(!nextIndex) { - if(this._source instanceof def.Query) { - if(this._source instanceof def.ArrayLikeQuery){ - this._source = this._source._list; - } else { - this._source = this._source.array(); - } - } // else assume array-like - - this._count = this._source.length; - } - - var count = this._count; - if(nextIndex < count){ - var index = count - nextIndex - 1; - var source = this._source; - - while(!objectHasOwn.call(source, index)){ - if(--index < 0){ - return 0; - } - this._count--; - } - - this.item = source[index]; - return 1; - } - } -}); - - -// ------------------- - -def.query = function(q){ - if(q === undefined) { - return new def.NullQuery(); - } - - if(q instanceof def.Query){ - return q; - } - - if(def.fun.is(q)){ - return new def.AdhocQuery(q); - } - - return new def.ArrayLikeQuery(q); -}; - -def.range = function(start, count, step){ - return new def.RangeQuery(start, count, step); -}; - -// Reset namespace to global, instead of 'def' -currentNamespace = def.global; \ No newline at end of file diff --git a/pacotes/ccc2/lib/jquery.tipsy.js b/pacotes/ccc2/lib/jquery.tipsy.js deleted file mode 100755 index bfd2906..0000000 --- a/pacotes/ccc2/lib/jquery.tipsy.js +++ /dev/null @@ -1,319 +0,0 @@ -// tipsy, facebook style tooltips for jquery -// version 1.0.0a -// (c) 2008-2010 jason frame [jason@onehackoranother.com] -// releated under the MIT license - -(function($) { - - function fixTitle($ele) { - var title = $ele.attr('title'); - if (title || typeof($ele.attr('original-title')) !== 'string') { - $ele.attr('original-title', title || '') - .removeAttr('title'); - } - } - - function Tipsy(element, options) { - this.$element = $(element); - this.options = options; - this.enabled = true; - fixTitle(this.$element); - } - - Tipsy.prototype = { - enter: function() { - var tipsy = this; - var options = this.options; - - tipsy.hoverState = 'in'; - if (options.delayIn == 0) { - tipsy.show(); - } else { - setTimeout(function() { - if (tipsy.hoverState === 'in') { - tipsy.hoverState = null; - tipsy.show(); - } - }, options.delayIn); - } - }, - - leave: function() { - var tipsy = this; - var options = this.options; - - tipsy.hoverState = 'out'; - if (options.delayOut == 0) { - tipsy.hide(); - } else { - setTimeout(function() { if (tipsy.hoverState === 'out') tipsy.hide(); }, options.delayOut); - } - }, - - visible: function(){ - var parent; - return this.hoverState === 'in' || // almost visible - (this.hoverState !== 'out' && - !!(this.$tip && - (parent = this.$tip[0].parentNode) && - (parent.nodeType !== 11))); // Document fragment - }, - - update: function(){ - if(this.visible()){ - this.show(true); - } else { - this.enter(); - } - }, - - show: function(isUpdate) { - // Don't override delay in - if (this.hoverState === 'in') { - return; - } - - var title = this.getTitle(); - if (!this.enabled || !title) { - this.hoverState = null; - this.hide(); - return; - } - - var $tip = this.tip(); - $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title); - $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity - - if(!isUpdate){ - $tip.remove(); - } - - var parent = $tip[0].parentNode; - if(!parent || (parent.nodeType === 11)){ // Document fragment - $tip.css({top: 0, left: 0, visibility: 'hidden', display: 'block'}) - .appendTo(document.body); - } - - var pos = $.extend({}, this.$element.offset()); - - // Adds SVG support. - // Modified from https://github.com/logical42/tipsy-svg--for-rails - if (this.$element[0].nearestViewportElement) { - var rect = this.$element[0].getBoundingClientRect(); - pos.width = rect.width; - pos.height = rect.height; - } else { - pos.width = this.$element[0].offsetWidth || 0; - pos.height = this.$element[0].offsetHeight || 0; - } - - var tipOffset = this.options.offset, - useCorners = this.options.useCorners, - showArrow = this.options.arrowVisible, - actualWidth = $tip[0].offsetWidth, - actualHeight = $tip[0].offsetHeight; - - if(!showArrow){ - // More or less the padding reserved for the arrow - tipOffset -= 4; - } - - function calcPosition(gravity){ - var tp; - switch (gravity.charAt(0)) { - case 'n': - tp = {top: pos.top + pos.height + tipOffset, left: pos.left + pos.width / 2 - actualWidth / 2}; - break; - case 's': - tp = {top: pos.top - actualHeight - tipOffset, left: pos.left + pos.width / 2 - actualWidth / 2}; - break; - case 'e': - tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - tipOffset}; - break; - case 'w': - tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + tipOffset}; - break; - } - - if (gravity.length === 2) { - if (gravity.charAt(1) == 'w') { - tp.left = useCorners ? - pos.left + pos.width + tipOffset: - pos.left + pos.width / 2 - 15; - } else { - tp.left = useCorners ? - pos.left - actualWidth - tipOffset : - pos.left + pos.width / 2 - actualWidth + 15; - } - } - - return tp; - } - - var gravity = (typeof this.options.gravity == 'function') - ? this.options.gravity.call(this.$element[0], {width: actualWidth, height: actualHeight}, calcPosition) - : this.options.gravity; - - var tp = calcPosition(gravity); - - // Add a duplicate w/e char at the end when using corners - $tip.css(tp) - .addClass('tipsy-' + gravity + (useCorners && gravity.length > 1 ? gravity.charAt(1) : '')); - - if(showArrow){ - var hideArrow = useCorners && gravity.length === 2; - // If corner, hide the arrow, cause arrow styles don't support corners nicely - $tip.find('.tipsy-arrow')[hideArrow ? 'hide' : 'show'](); - } - - var doFadeIn = this.options.fade && (!isUpdate || !this._prevGravity || (this._prevGravity !== gravity)); - if (doFadeIn) { - $tip.stop() - .css({opacity: 0, display: 'block', visibility: 'visible'}) - .animate({opacity: this.options.opacity}); - } else { - $tip.css({visibility: 'visible', opacity: this.options.opacity}); - } - - this._prevGravity = gravity; - - this.hoverState = null; - }, - - hide: function() { - if (this.options.fade) { - this.tip().stop().fadeOut(function() { $(this).remove(); }); - } else if(this.$tip){ - this.tip().remove(); - } - - this.hoverState = null; - }, - - setTitle: function(title) { - title = (title == null) ? "" : ("" + title); - this.$element - .attr('original-title', title) - .removeAttr('title'); - }, - - getTitle: function() { - var title, $e = this.$element, o = this.options; - fixTitle($e); - if (typeof o.title === 'string') { - title = $e.attr(o.title == 'title' ? 'original-title' : o.title); - } else if (typeof o.title === 'function') { - title = o.title.call($e[0]); - } - title = ('' + title).replace(/(^\s*|\s*$)/, ""); - return title || o.fallback; - }, - - tip: function() { - if (!this.$tip) { - this.$tip = $('
'); - if(this.options.arrowVisible){ - this.$tip.html('
'); - } else { - this.$tip.html('
'); - } - - // Remove it from document fragment parent - // So that visible tests do not fail - // Does not work on IE - this.$tip.remove(); - } - return this.$tip; - }, - - validate: function() { - var parent = this.$element[0].parentNode; - if (!parent || (parent.nodeType === 11)){ - this.hide(); - this.$element = null; - this.options = null; - } - }, - - enable: function() { this.enabled = true; }, - disable: function() { this.enabled = false; }, - toggleEnabled: function() { this.enabled = !this.enabled; } - }; - - $.fn.tipsy = function(options, arg) { - - if (options === true) { - return this.data('tipsy'); - } else if (typeof options === 'string') { - return this.data('tipsy')[options](arg); - } - - options = $.extend({}, $.fn.tipsy.defaults, options); - if(options.arrowVisible == null){ - options.arrowVisible = !options.useCorners; - } - - function get(ele) { - var tipsy = $.data(ele, 'tipsy'); - if (!tipsy) { - tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options)); - $.data(ele, 'tipsy', tipsy); - } - return tipsy; - } - - function enter() { - get(this).enter(); - } - - function leave() { - get(this).leave(); - } - - if (!options.live) this.each(function() { get(this); }); - - if (options.trigger != 'manual') { - var binder = options.live ? 'live' : 'bind', - eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus', - eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'; - this[binder](eventIn, enter) - [binder](eventOut, leave); - } - - return this; - - }; - - $.fn.tipsy.defaults = { - delayIn: 0, - delayOut: 0, - fade: false, - fallback: '', - gravity: 'n', - html: false, - live: false, - offset: 0, - opacity: 0.8, - title: 'title', - trigger: 'hover', - useCorners: false, // use corners in nw, ne and sw, se gravities - arrowVisible: null // show or hide the arrow (default is !useCorners) - }; - - // Overwrite this method to provide options on a per-element basis. - // For example, you could store the gravity in a 'tipsy-gravity' attribute: - // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' }); - // (remember - do not modify 'options' in place!) - $.fn.tipsy.elementOptions = function(ele, options) { - return $.metadata ? $.extend({}, options, $(ele).metadata()) : options; - }; - - $.fn.tipsy.autoNS = function() { - return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n'; - }; - - $.fn.tipsy.autoWE = function() { - return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w'; - }; - -})(jQuery); diff --git a/pacotes/ccc2/lib/protovis-d3.3.js b/pacotes/ccc2/lib/protovis-d3.3.js deleted file mode 100755 index 78ae5ab..0000000 --- a/pacotes/ccc2/lib/protovis-d3.3.js +++ /dev/null @@ -1,21790 +0,0 @@ -// 756a9aed812293ce02110c9ea318a99340b04df1 -/** - * @class The built-in Array class. - * @name Array - */ - -/** - * Creates a new array with the results of calling a provided function on every - * element in this array. Implemented in Javascript 1.6. - * - * @function - * @name Array.prototype.map - * @see map - * documentation. - * @param {function} f function that produces an element of the new Array from - * an element of the current one. - * @param [o] object to use as this when executing f. - */ -if (!Array.prototype.map) Array.prototype.map = function(f, o) { - var n = this.length; - var result = new Array(n); - for (var i = 0; i < n; i++) { - if (i in this) { - result[i] = f.call(o, this[i], i, this); - } - } - return result; -}; - -/** - * Creates a new array with all elements that pass the test implemented by the - * provided function. Implemented in Javascript 1.6. - * - * @function - * @name Array.prototype.filter - * @see filter - * documentation. - * @param {function} f function to test each element of the array. - * @param [o] object to use as this when executing f. - */ -if (!Array.prototype.filter) Array.prototype.filter = function(f, o) { - var n = this.length; - var result = new Array(); - for (var i = 0; i < n; i++) { - if (i in this) { - var v = this[i]; - if (f.call(o, v, i, this)) result.push(v); - } - } - return result; -}; - -/** - * Executes a provided function once per array element. Implemented in - * Javascript 1.6. - * - * @function - * @name Array.prototype.forEach - * @see forEach - * documentation. - * @param {function} f function to execute for each element. - * @param [o] object to use as this when executing f. - */ -if (!Array.prototype.forEach) Array.prototype.forEach = function(f, o) { - var n = this.length >>> 0; - for (var i = 0; i < n; i++) { - if (i in this) f.call(o, this[i], i, this); - } -}; - -/** - * Apply a function against an accumulator and each value of the array (from - * left-to-right) as to reduce it to a single value. Implemented in Javascript - * 1.8. - * - * @function - * @name Array.prototype.reduce - * @see reduce - * documentation. - * @param {function} f function to execute on each value in the array. - * @param [v] object to use as the first argument to the first call of - * t. - */ -if (!Array.prototype.reduce) Array.prototype.reduce = function(f, v) { - var len = this.length; - if (!len && (arguments.length == 1)) { - throw new Error("reduce: empty array, no initial value"); - } - - var i = 0; - if (arguments.length < 2) { - while (true) { - if (i in this) { - v = this[i++]; - break; - } - if (++i >= len) { - throw new Error("reduce: no values, no initial value"); - } - } - } - - for (; i < len; i++) { - if (i in this) { - v = f(v, this[i], i, this); - } - } - return v; -}; -/** - * The top-level Protovis namespace. All public methods and fields should be - * registered on this object. Note that core Protovis source is surrounded by an - * anonymous function, so any other declared globals will not be visible outside - * of core methods. This also allows multiple versions of Protovis to coexist, - * since each version will see their own pv namespace. - * - * @namespace The top-level Protovis namespace, pv. - */ -var pv = {}; - -/** - * Protovis major and minor version numbers. - * - * @namespace Protovis major and minor version numbers. - */ -pv.version = { - /** - * The major version number. - * - * @type number - * @constant - */ - major: 3, - - /** - * The minor version number. - * - * @type number - * @constant - */ - minor: 3 -}; - -/** - * Returns the passed-in argument, x; the identity function. This method - * is provided for convenience since it is used as the default behavior for a - * number of property functions. - * - * @param x a value. - * @returns the value x. - */ -pv.identity = function(x) { return x; }; - -/** - * Returns this.index. This method is provided for convenience for use - * with scales. For example, to color bars by their index, say: - * - *
.fillStyle(pv.Colors.category10().by(pv.index))
- * - * This method is equivalent to function() this.index, but more - * succinct. Note that the index property is also supported for - * accessor functions with {@link pv.max}, {@link pv.min} and other array - * utility methods. - * - * @see pv.Scale - * @see pv.Mark#index - */ -pv.index = function() { return this.index; }; - -/** - * Returns this.childIndex. This method is provided for convenience for - * use with scales. For example, to color bars by their child index, say: - * - *
.fillStyle(pv.Colors.category10().by(pv.child))
- * - * This method is equivalent to function() this.childIndex, but more - * succinct. - * - * @see pv.Scale - * @see pv.Mark#childIndex - */ -pv.child = function() { return this.childIndex; }; - -/** - * Returns this.parent.index. This method is provided for convenience - * for use with scales. This method is provided for convenience for use with - * scales. For example, to color bars by their parent index, say: - * - *
.fillStyle(pv.Colors.category10().by(pv.parent))
- * - * This method is equivalent to function() this.parent.index, but more - * succinct. - * - * @see pv.Scale - * @see pv.Mark#index - */ -pv.parent = function() { return this.parent.index; }; - -/** - * Stores the current event. This field is only set within event handlers. - * - * @type Event - * @name pv.event - */ -/** - * @private Returns a prototype object suitable for extending the given class - * f. Rather than constructing a new instance of f to serve as - * the prototype (which unnecessarily runs the constructor on the created - * prototype object, potentially polluting it), an anonymous function is - * generated internally that shares the same prototype: - * - *
function g() {}
- * g.prototype = f.prototype;
- * return new g();
- * - * For more details, see Douglas Crockford's essay on prototypal inheritance. - * - * @param {function} f a constructor. - * @returns a suitable prototype object. - * @see Douglas Crockford's essay on prototypal - * inheritance. - */ -pv.extend = Object.create ? - function(f){ - return Object.create(f.prototype || f); - } : - function(f) { - function g() {} - g.prototype = f.prototype || f; - return new g(); - }; - -// Is there any browser (still) supporting this syntax? -// Commented cause this messes up with the debugger's break on exceptions. - -//try { -// eval("pv.parse = function(x) x;"); // native support -//} catch (e) { - -/** - * @private Parses a Protovis specification, which may use JavaScript 1.8 - * function expresses, replacing those function expressions with proper - * functions such that the code can be run by a JavaScript 1.6 interpreter. This - * hack only supports function expressions (using clumsy regular expressions, no - * less), and not other JavaScript 1.8 features such as let expressions. - * - * @param {string} s a Protovis specification (i.e., a string of JavaScript 1.8 - * source code). - * @returns {string} a conformant JavaScript 1.6 source code. - */ -pv.parse = function(js) { // hacky regex support - var re = new RegExp("function\\s*(\\b\\w+)?\\s*\\([^)]*\\)\\s*", "mg"), m, d, i = 0, s = ""; - while (m = re.exec(js)) { - var j = m.index + m[0].length; - if (js.charAt(j) != '{') { - s += js.substring(i, j) + "{return "; - i = j; - for (var p = 0; p >= 0 && j < js.length; j++) { - var c = js.charAt(j); - switch (c) { - case '"': case '\'': { - while (++j < js.length && (d = js.charAt(j)) != c) { - if (d == '\\') j++; - } - break; - } - case '[': case '(': p++; break; - case ']': case ')': p--; break; - case ';': - case ',': if (p == 0) p--; break; - } - } - s += pv.parse(js.substring(i, --j)) + ";}"; - i = j; - } - re.lastIndex = j; - } - s += js.substring(i); - return s; - }; -//} - -/** - * @private Computes the value of the specified CSS property p on the - * specified element e. - * - * @param {string} p the name of the CSS property. - * @param e the element on which to compute the CSS property. - */ -pv.css = function(e, p) { - return window.getComputedStyle - ? window.getComputedStyle(e, null).getPropertyValue(p) - : e.currentStyle[p]; -}; - -/** - * @private Reports the specified error to the JavaScript console. Mozilla only - * allows logging to the console for privileged code; if the console is - * unavailable, the alert dialog box is used instead. - * - * @param e the exception that triggered the error. - */ -pv.error = function(e) { - (typeof console === "undefined" || !console.error) ? alert(e) : console.error(e); -}; - -/** - * @private Registers the specified listener for events of the specified type on - * the specified target. For standards-compliant browsers, this method uses - * addEventListener; for Internet Explorer, attachEvent. - * - * @param target a DOM element. - * @param {string} type the type of event, such as "click". - * @param {function} the event handler callback. - */ -pv.listen = function(target, type, listener) { - if (type === 'load' || type === 'onload'){ - return pv.listenForPageLoad(pv.listener(listener)); - } - - listener = pv.listener(listener); - target.addEventListener - ? target.addEventListener(type, listener, false) - : target.attachEvent('on' + type, listener); - - return listener; -}; - -/** - * @private Unregisters the specified listener for events of the specified type on - * the specified target. - * - * @param target a DOM element. - * @param {string} type the type of event, such as "click". - * @param {function} the event handler callback or the result of {@link pv.listen}. - */ -pv.unlisten = function(target, type, listener){ - if(listener.$listener){ - listener = listener.$listener; - } - - target.removeEventListener - ? target.removeEventListener(type, listener, false) - : target.detachEvent('on' + type, listener); -}; - -/** - * @private Returns a wrapper for the specified listener function such that the - * {@link pv.event} is set for the duration of the listener's invocation. The - * wrapper is cached on the returned function, such that duplicate registrations - * of the wrapped event handler are ignored. - * - * @param {function} f an event handler. - * @returns {function} the wrapped event handler. - */ -pv.listener = function(f) { - return f.$listener || (f.$listener = function(e) { - if(e != undefined){ - try { - // Fix event (adapted from jQuery) - if(e.pageX == null && e.clientX != null) { - var eventDoc = (e.target && e.target.ownerDocument) || document; - var doc = eventDoc.documentElement; - var body = eventDoc.body; - - e.pageX = (e.clientX * 1) + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - e.pageY = (e.clientY * 1) + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - pv.event = e; - - return f.call(this, e); - } catch (ex) { - // swallow top level error - pv.error(ex); - } finally { - delete pv.event; - } - } - }); -}; - -/** - * @private Returns true iff a is an ancestor of e. This is useful - * for ignoring mouseout and mouseover events that are contained within the - * target element. - */ -pv.ancestor = function(a, e) { - while (e) { - if (e == a) return true; - e = e.parentNode; - } - return false; -}; - -pv.getWindow = function(elem) { - return (elem != null && elem == elem.window) ? - elem : - elem.nodeType === 9 ? - elem.defaultView || elem.parentWindow : - false; -}; - -/* Adapted from jQuery.offset() - */ -pv.elementOffset = function(elem) { - var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft, - box = { top: 0, left: 0 }, - doc = elem && elem.ownerDocument; - - if (!doc) { - return; - } - - body = doc.body; - if(body === elem) { - return; // not supported - } - - docElem = doc.documentElement; - - if ( typeof elem.getBoundingClientRect !== "undefined" ) { - box = elem.getBoundingClientRect(); - } - - win = pv.getWindow(doc); - - clientTop = docElem.clientTop || body.clientTop || 0; - clientLeft = docElem.clientLeft || body.clientLeft || 0; - scrollTop = win.pageYOffset || docElem.scrollTop; - scrollLeft = win.pageXOffset || docElem.scrollLeft; - return { - top: box.top + scrollTop - clientTop, - left: box.left + scrollLeft - clientLeft - }; -}; - -/** - * Binds to the page ready event in a browser-agnostic - * fashion (i.e. that works under IE!) - */ -pv.listenForPageLoad = function(listener) { - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - listener(); - } - - if (pv.renderer() == "svgweb") { - // SVG web adds addEventListener to IE. - window.addEventListener( "SVGLoad", listener, false ); - } else { - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - window.addEventListener( "load", listener, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - window.attachEvent( "onload", listener ); - } - } -}; - -/** - * @public Returns the name of the renderer we're using - - * - * 'nativesvg' is the default - the native svg of the browser. - * 'svgweb' is if we identify svgweb is there. - */ - -pv.renderer = function(){ - var renderer = (typeof document.svgImplementation !== "undefined") ? - document.svgImplementation : - (typeof window.svgweb === "undefined") ? "nativesvg" : "svgweb"; - - pv.renderer = function(){ return renderer; }; - - return renderer; -}; - -/** @private Returns a locally-unique positive id. */ -pv.id = function() { - var id = 1; return function() { return id++; }; -}(); - -/** @private Returns a function wrapping the specified constant. */ -pv.functor = function(v) { - return typeof v == "function" ? v : function() { return v; }; -}; - -/** - * Gets the value of an existing, own or inherited, and not "nully", property of an object, - * or if unsatisfied, a specified default value. - * - * @param {object} [o] The object whose property value is desired. - * @param {string} p The desired property name. - * If the value is not a string, - * it is converted to one, as if String(p) were used. - * @param [dv=undefined] The default value. - * - * @returns {any} The satisfying property value or the specified default value. - */ -pv.get = function(o, p, dv){ - var v; - return o && (v = o[p]) != null ? v : dv; -}; -/* - * Parses the Protovis specifications on load, allowing the use of JavaScript - * 1.8 function expressions on browsers that only support JavaScript 1.6. - * This should only happen for browser environments, so we exclude batik. - * @see pv.parse - */ -if (pv.renderer() !== "batik") { - pv.listen(window, "load", function() { - /* - * Note: in Firefox any variables declared here are visible to the eval'd - * script below. Even worse, any global variables declared by the script - * could overwrite local variables here (such as the index, `i`)! To protect - * against this, all variables are explicitly scoped on a pv.$ object. - */ - pv.$ = {i:0, x:document.getElementsByTagName("script")}; - pv.$.xlen = pv.$.x.length; - for (; pv.$.i < pv.$.xlen; pv.$.i++) { - pv.$.s = pv.$.x[pv.$.i]; - if (pv.$.s.type == "text/javascript+protovis") { - try { - window.eval(pv.parse(pv.$.s.text)); - } catch (e) { - pv.error(e); - } - } - } - delete pv.$; - }); -} -/** - * Abstract; see an implementing class. - * - * @class Represents an abstract text formatter and parser. A format is a - * function that converts an object of a given type, such as a Date, to - * a human-readable string representation. The format may also have a - * {@link #parse} method for converting a string representation back to the - * given object type. - * - *

Because formats are themselves functions, they can be used directly as - * mark properties. For example, if the data associated with a label are dates, - * a date format can be used as label text: - * - *

    .text(pv.Format.date("%m/%d/%y"))
- * - * And as with scales, if the format is used in multiple places, it can be - * convenient to declare it as a global variable and then reference it from the - * appropriate property functions. For example, if the data has a date - * attribute, and format references a given date format: - * - *
    .text(function(d) format(d.date))
- * - * Similarly, to parse a string into a date: - * - *
var date = format.parse("4/30/2010");
- * - * Not all format implementations support parsing. See the implementing class - * for details. - * - * @see pv.Format.date - * @see pv.Format.number - * @see pv.Format.time - */ -pv.Format = {}; - -/** - * Formats the specified object, returning the string representation. - * - * @function - * @name pv.Format.prototype.format - * @param {object} x the object to format. - * @returns {string} the formatted string. - */ - -/** - * Parses the specified string, returning the object representation. - * - * @function - * @name pv.Format.prototype.parse - * @param {string} x the string to parse. - * @returns {object} the parsed object. - */ - -/** - * @private Given a string that may be used as part of a regular expression, - * this methods returns an appropriately quoted version of the specified string, - * with any special characters escaped. - * - * @param {string} s a string to quote. - * @returns {string} the quoted string. - */ -pv.Format.re = function(s) { - return s.replace(/[\\\^\$\*\+\?\[\]\(\)\.\{\}]/g, "\\$&"); -}; - -/** - * @private Optionally pads the specified string s so that it is at least - * n characters long, using the padding character c. - * - * @param {string} c the padding character. - * @param {number} n the minimum string length. - * @param {string} s the string to pad. - * @returns {string} the padded string. - */ -pv.Format.pad = function(c, n, s) { - var m = n - String(s).length; - return (m < 1) ? s : new Array(m + 1).join(c) + s; -}; -/** - * Constructs a new date format with the specified string pattern. - * - * @class The format string is in the same format expected by the - * strftime function in C. The following conversion specifications are - * supported:
    - * - *
  • %a - abbreviated weekday name.
  • - *
  • %A - full weekday name.
  • - *
  • %b - abbreviated month names.
  • - *
  • %B - full month names.
  • - *
  • %c - locale's appropriate date and time.
  • - *
  • %C - century number.
  • - *
  • %d - day of month [01,31] (zero padded).
  • - *
  • %D - same as %m/%d/%y.
  • - *
  • %e - day of month [ 1,31] (space padded).
  • - *
  • %h - same as %b.
  • - *
  • %H - hour (24-hour clock) [00,23] (zero padded).
  • - *
  • %I - hour (12-hour clock) [01,12] (zero padded).
  • - *
  • %m - month number [01,12] (zero padded).
  • - *
  • %M - minute [0,59] (zero padded).
  • - *
  • %n - newline character.
  • - *
  • %p - locale's equivalent of a.m. or p.m.
  • - *
  • %r - same as %I:%M:%S %p.
  • - *
  • %R - same as %H:%M.
  • - *
  • %S - second [00,61] (zero padded).
  • - *
  • %t - tab character.
  • - *
  • %T - same as %H:%M:%S.
  • - *
  • %x - same as %m/%d/%y.
  • - *
  • %X - same as %I:%M:%S %p.
  • - *
  • %y - year with century [00,99] (zero padded).
  • - *
  • %Y - year including century.
  • - *
  • %% - %.
  • - * - *
The following conversion specifications are currently unsupported - * for formatting:
    - * - *
  • %j - day number [1,366].
  • - *
  • %u - weekday number [1,7].
  • - *
  • %U - week number [00,53].
  • - *
  • %V - week number [01,53].
  • - *
  • %w - weekday number [0,6].
  • - *
  • %W - week number [00,53].
  • - *
  • %Z - timezone name or abbreviation.
  • - * - *
In addition, the following conversion specifications are currently - * unsupported for parsing:
    - * - *
  • %a - day of week, either abbreviated or full name.
  • - *
  • %A - same as %a.
  • - *
  • %c - locale's appropriate date and time.
  • - *
  • %C - century number.
  • - *
  • %D - same as %m/%d/%y.
  • - *
  • %I - hour (12-hour clock) [1,12].
  • - *
  • %n - any white space.
  • - *
  • %p - locale's equivalent of a.m. or p.m.
  • - *
  • %r - same as %I:%M:%S %p.
  • - *
  • %R - same as %H:%M.
  • - *
  • %t - same as %n.
  • - *
  • %T - same as %H:%M:%S.
  • - *
  • %x - locale's equivalent to %m/%d/%y.
  • - *
  • %X - locale's equivalent to %I:%M:%S %p.
  • - * - *
- * - * @see strftime - * documentation. - * @see strptime - * documentation. - * @extends pv.Format - * @param {string} pattern the format pattern. - */ -pv.Format.date = function(pattern) { - var pad = pv.Format.pad; - - /** @private */ - function format(d) { - return pattern.replace(/%[a-zA-Z0-9]/g, function(s) { - switch (s) { - case '%a': return [ - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" - ][d.getDay()]; - case '%A': return [ - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", - "Saturday" - ][d.getDay()]; - case '%h': - case '%b': return [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", - "Oct", "Nov", "Dec" - ][d.getMonth()]; - case '%B': return [ - "January", "February", "March", "April", "May", "June", "July", - "August", "September", "October", "November", "December" - ][d.getMonth()]; - case '%c': return d.toLocaleString(); - case '%C': return pad("0", 2, Math.floor(d.getFullYear() / 100) % 100); - case '%d': return pad("0", 2, d.getDate()); - case '%x': - case '%D': return pad("0", 2, d.getMonth() + 1) - + "/" + pad("0", 2, d.getDate()) - + "/" + pad("0", 2, d.getFullYear() % 100); - case '%e': return pad(" ", 2, d.getDate()); - case '%H': return pad("0", 2, d.getHours()); - case '%I': { - var h = d.getHours() % 12; - return h ? pad("0", 2, h) : 12; - } - // TODO %j: day of year as a decimal number [001,366] - case '%m': return pad("0", 2, d.getMonth() + 1); - case '%M': return pad("0", 2, d.getMinutes()); - case '%n': return "\n"; - case '%p': return d.getHours() < 12 ? "AM" : "PM"; - case '%T': - case '%X': - case '%r': { - var h = d.getHours() % 12; - return (h ? pad("0", 2, h) : 12) - + ":" + pad("0", 2, d.getMinutes()) - + ":" + pad("0", 2, d.getSeconds()) - + " " + (d.getHours() < 12 ? "AM" : "PM"); - } - case '%R': return pad("0", 2, d.getHours()) + ":" + pad("0", 2, d.getMinutes()); - case '%S': return pad("0", 2, d.getSeconds()); - case '%Q': return pad("0", 3, d.getMilliseconds()); - case '%t': return "\t"; - case '%u': { - var w = d.getDay(); - return w ? w : 1; - } - // TODO %U: week number (sunday first day) [00,53] - // TODO %V: week number (monday first day) [01,53] ... with weirdness - case '%w': return d.getDay(); - // TODO %W: week number (monday first day) [00,53] ... with weirdness - case '%y': return pad("0", 2, d.getFullYear() % 100); - case '%Y': return d.getFullYear(); - // TODO %Z: timezone name or abbreviation - case '%%': return "%"; - } - return s; - }); - } - - /** - * Converts a date to a string using the associated formatting pattern. - * - * @function - * @name pv.Format.date.prototype.format - * @param {Date} date a date to format. - * @returns {string} the formatted date as a string. - */ - format.format = format; - - /** - * Parses a date from a string using the associated formatting pattern. - * - * @function - * @name pv.Format.date.prototype.parse - * @param {string} s the string to parse as a date. - * @returns {Date} the parsed date. - */ - format.parse = function(s) { - var year = 1970, month = 0, date = 1, hour = 0, minute = 0, second = 0; - var fields = [function() {}]; - - /* Register callbacks for each field in the format pattern. */ - var re = pv.Format.re(pattern).replace(/%[a-zA-Z0-9]/g, function(s) { - switch (s) { - // TODO %a: day of week, either abbreviated or full name - // TODO %A: same as %a - case '%b': { - fields.push(function(x) { month = { - Jan: 0, Feb: 1, Mar: 2, Apr: 3, May: 4, Jun: 5, Jul: 6, Aug: 7, - Sep: 8, Oct: 9, Nov: 10, Dec: 11 - }[x]; }); - return "([A-Za-z]+)"; - } - case '%h': - case '%B': { - fields.push(function(x) { month = { - January: 0, February: 1, March: 2, April: 3, May: 4, June: 5, - July: 6, August: 7, September: 8, October: 9, November: 10, - December: 11 - }[x]; }); - return "([A-Za-z]+)"; - } - // TODO %c: locale's appropriate date and time - // TODO %C: century number[0,99] - case '%e': - case '%d': { - fields.push(function(x) { date = x; }); - return "([0-9]+)"; - } - // TODO %D: same as %m/%d/%y - case '%I': - case '%H': { - fields.push(function(x) { hour = x; }); - return "([0-9]+)"; - } - // TODO %j: day number [1,366] - case '%m': { - fields.push(function(x) { month = x - 1; }); - return "([0-9]+)"; - } - case '%M': { - fields.push(function(x) { minute = x; }); - return "([0-9]+)"; - } - // TODO %n: any white space - // TODO %p: locale's equivalent of a.m. or p.m. - case '%p': { // TODO this is a hack - fields.push(function(x) { - if (hour == 12) { - if (x == "am") hour = 0; - } else if (x == "pm") { - hour = Number(hour) + 12; - } - }); - return "(am|pm)"; - } - // TODO %r: %I:%M:%S %p - // TODO %R: %H:%M - case '%S': { - fields.push(function(x) { second = x; }); - return "([0-9]+)"; - } - // TODO %t: any white space - // TODO %T: %H:%M:%S - // TODO %U: week number [00,53] - // TODO %w: weekday [0,6] - // TODO %W: week number [00, 53] - // TODO %x: locale date (%m/%d/%y) - // TODO %X: locale time (%I:%M:%S %p) - case '%y': { - fields.push(function(x) { - x = Number(x); - year = x + (((0 <= x) && (x < 69)) ? 2000 - : (((x >= 69) && (x < 100) ? 1900 : 0))); - }); - return "([0-9]+)"; - } - case '%Y': { - fields.push(function(x) { year = x; }); - return "([0-9]+)"; - } - case '%%': { - fields.push(function() {}); - return "%"; - } - } - return s; - }); - - var match = s.match(re); - if (match) match.forEach(function(m, i) { fields[i](m); }); - return new Date(year, month, date, hour, minute, second); - }; - - return format; -}; -/** - * Returns a time format of the given type, either "short" or "long". - * - * @class Represents a time format, converting between a number - * representing a duration in milliseconds, and a string. Two types of - * time formats are supported: "short" and "long". The short format type - * returns a string such as "3.3 days" or "12.1 minutes", while the long - * format returns "13:04:12" or similar. - * - * @extends pv.Format - * @param {string} type the type; "short" or "long". - */ -pv.Format.time = function(type) { - var pad = pv.Format.pad; - - /* - * MILLISECONDS = 1 - * SECONDS = 1e3 - * MINUTES = 6e4 - * HOURS = 36e5 - * DAYS = 864e5 - * WEEKS = 6048e5 - * MONTHS = 2592e6 - * YEARS = 31536e6 - */ - - /** @private */ - function format(t) { - t = Number(t); // force conversion from Date - switch (type) { - case "short": { - if (t >= 31536e6) { - return (t / 31536e6).toFixed(1) + " years"; - } else if (t >= 6048e5) { - return (t / 6048e5).toFixed(1) + " weeks"; - } else if (t >= 864e5) { - return (t / 864e5).toFixed(1) + " days"; - } else if (t >= 36e5) { - return (t / 36e5).toFixed(1) + " hours"; - } else if (t >= 6e4) { - return (t / 6e4).toFixed(1) + " minutes"; - } - return (t / 1e3).toFixed(1) + " seconds"; - } - case "long": { - var a = [], - s = ((t % 6e4) / 1e3) >> 0, - m = ((t % 36e5) / 6e4) >> 0; - a.push(pad("0", 2, s)); - if (t >= 36e5) { - var h = ((t % 864e5) / 36e5) >> 0; - a.push(pad("0", 2, m)); - if (t >= 864e5) { - a.push(pad("0", 2, h)); - a.push(Math.floor(t / 864e5).toFixed()); - } else { - a.push(h.toFixed()); - } - } else { - a.push(m.toFixed()); - } - return a.reverse().join(":"); - } - } - } - - /** - * Formats the specified time, returning the string representation. - * - * @function - * @name pv.Format.time.prototype.format - * @param {number} t the duration in milliseconds. May also be a Date. - * @returns {string} the formatted string. - */ - format.format = format; - - /** - * Parses the specified string, returning the time in milliseconds. - * - * @function - * @name pv.Format.time.prototype.parse - * @param {string} s a formatted string. - * @returns {number} the parsed duration in milliseconds. - */ - format.parse = function(s) { - switch (type) { - case "short": { - var re = /([0-9,.]+)\s*([a-z]+)/g, a, t = 0; - while (a = re.exec(s)) { - var f = parseFloat(a[0].replace(",", "")), u = 0; - switch (a[2].toLowerCase()) { - case "year": case "years": u = 31536e6; break; - case "week": case "weeks": u = 6048e5; break; - case "day": case "days": u = 864e5; break; - case "hour": case "hours": u = 36e5; break; - case "minute": case "minutes": u = 6e4; break; - case "second": case "seconds": u = 1e3; break; - } - t += f * u; - } - return t; - } - case "long": { - var a = s.replace(",", "").split(":").reverse(), t = 0; - if (a.length) t += parseFloat(a[0]) * 1e3; - if (a.length > 1) t += parseFloat(a[1]) * 6e4; - if (a.length > 2) t += parseFloat(a[2]) * 36e5; - if (a.length > 3) t += parseFloat(a[3]) * 864e5; - return t; - } - } - } - - return format; -}; -/** - * Returns a default number format. - * - * @class Represents a number format, converting between a number and a - * string. This class allows numbers to be formatted with variable - * precision (both for the integral and fractional part of the number), optional - * thousands grouping, and optional padding. The thousands (",") and decimal - * (".") separator can be customized. - * - * @returns {pv.Format.number} a number format. - */ -pv.Format.number = function() { - var mini = 0, // default minimum integer digits - maxi = Infinity, // default maximum integer digits - mins = 0, // mini, including group separators - minf = 0, // default minimum fraction digits - maxf = 0, // default maximum fraction digits - maxk = 1, // 10^maxf - padi = "0", // default integer pad - padf = "0", // default fraction pad - padg = true, // whether group separator affects integer padding - decimal = ".", // default decimal separator - group = ",", // default group separator - np = "\u2212", // default negative prefix - ns = ""; // default negative suffix - - /** @private */ - function format(x) { - /* Round the fractional part, and split on decimal separator. */ - if (Infinity > maxf) x = Math.round(x * maxk) / maxk; - var s = String(Math.abs(x)).split("."); - - /* Pad, truncate and group the integral part. */ - var i = s[0]; - if (i.length > maxi) i = i.substring(i.length - maxi); - if (padg && (i.length < mini)) i = new Array(mini - i.length + 1).join(padi) + i; - if (i.length > 3) i = i.replace(/\B(?=(?:\d{3})+(?!\d))/g, group); - if (!padg && (i.length < mins)) i = new Array(mins - i.length + 1).join(padi) + i; - s[0] = x < 0 ? np + i + ns : i; - - /* Pad the fractional part. */ - var f = s[1] || ""; - if (f.length > maxf){ - // In IE9 64 bit strange things happen with floating points - // and the above division by maxk seems to sometimes result in - // floating point precision problems... - f = s[1] = f.substr(0, maxf); - } - - if (f.length < minf) s[1] = f + new Array(minf - f.length + 1).join(padf); - - return s.join(decimal); - } - - /** - * @function - * @name pv.Format.number.prototype.format - * @param {number} x - * @returns {string} - */ - format.format = format; - - /** - * Parses the specified string as a number. Before parsing, leading and - * trailing padding is removed. Group separators are also removed, and the - * decimal separator is replaced with the standard point ("."). The integer - * part is truncated per the maximum integer digits, and the fraction part is - * rounded per the maximum fraction digits. - * - * @function - * @name pv.Format.number.prototype.parse - * @param {string} x the string to parse. - * @returns {number} the parsed number. - */ - format.parse = function(x) { - var re = pv.Format.re; - - /* Remove leading and trailing padding. Split on the decimal separator, if exists. */ - var s = String(x).split(decimal); - if(s.length == 1) - s[1]=""; - s[0].replace(new RegExp("^(" + re(padi) + ")*"), ""); - s[1].replace(new RegExp("(" + re(padf) + ")*$"), "") - - /* Remove grouping and truncate the integral part. */ - var i = s[0].replace(new RegExp(re(group), "g"), ""); - if (i.length > maxi) i = i.substring(i.length - maxi); - - /* Round the fractional part. */ - var f = s[1] ? Number("0." + s[1]) : 0; - if (Infinity > maxf) f = Math.round(f * maxk) / maxk; - - return Math.round(i) + f; - }; - - /** - * Sets or gets the minimum and maximum number of integer digits. This - * controls the number of decimal digits to display before the decimal - * separator for the integral part of the number. If the number of digits is - * smaller than the minimum, the digits are padded; if the number of digits is - * larger, the digits are truncated, showing only the lower-order digits. The - * default range is [0, Infinity]. - * - *

If only one argument is specified to this method, this value is used as - * both the minimum and maximum number. If no arguments are specified, a - * two-element array is returned containing the minimum and the maximum. - * - * @function - * @name pv.Format.number.prototype.integerDigits - * @param {number} [min] the minimum integer digits. - * @param {number} [max] the maximum integer digits. - * @returns {pv.Format.number} this, or the current integer digits. - */ - format.integerDigits = function(min, max) { - if (arguments.length) { - mini = Number(min); - maxi = (arguments.length > 1) ? Number(max) : mini; - mins = mini + Math.floor(mini / 3) * group.length; - return this; - } - return [mini, maxi]; - }; - - /** - * Sets or gets the minimum and maximum number of fraction digits. The - * controls the number of decimal digits to display after the decimal - * separator for the fractional part of the number. If the number of digits is - * smaller than the minimum, the digits are padded; if the number of digits is - * larger, the fractional part is rounded, showing only the higher-order - * digits. The default range is [0, 0]. - * - *

If only one argument is specified to this method, this value is used as - * both the minimum and maximum number. If no arguments are specified, a - * two-element array is returned containing the minimum and the maximum. - * - * @function - * @name pv.Format.number.prototype.fractionDigits - * @param {number} [min] the minimum fraction digits. - * @param {number} [max] the maximum fraction digits. - * @returns {pv.Format.number} this, or the current fraction digits. - */ - format.fractionDigits = function(min, max) { - if (arguments.length) { - minf = Number(min); - maxf = (arguments.length > 1) ? Number(max) : minf; - maxk = Math.pow(10, maxf); - return this; - } - return [minf, maxf]; - }; - - /** - * Sets or gets the character used to pad the integer part. The integer pad is - * used when the number of integer digits is smaller than the minimum. The - * default pad character is "0" (zero). - * - * @param {string} [x] the new pad character. - * @returns {pv.Format.number} this or the current pad character. - */ - format.integerPad = function(x) { - if (arguments.length) { - padi = String(x); - padg = /\d/.test(padi); - return this; - } - return padi; - }; - - /** - * Sets or gets the character used to pad the fration part. The fraction pad - * is used when the number of fraction digits is smaller than the minimum. The - * default pad character is "0" (zero). - * - * @param {string} [x] the new pad character. - * @returns {pv.Format.number} this or the current pad character. - */ - format.fractionPad = function(x) { - if (arguments.length) { - padf = String(x); - return this; - } - return padf; - }; - - /** - * Sets or gets the character used as the decimal point, separating the - * integer and fraction parts of the number. The default decimal point is ".". - * - * @param {string} [x] the new decimal separator. - * @returns {pv.Format.number} this or the current decimal separator. - */ - format.decimal = function(x) { - if (arguments.length) { - decimal = String(x); - return this; - } - return decimal; - }; - - /** - * Sets or gets the character used as the group separator, grouping integer - * digits by thousands. The default decimal point is ",". Grouping can be - * disabled by using "" for the separator. - * - * @param {string} [x] the new group separator. - * @returns {pv.Format.number} this or the current group separator. - */ - format.group = function(x) { - if (arguments.length) { - group = x ? String(x) : ""; - mins = mini + Math.floor(mini / 3) * group.length; - return this; - } - return group; - }; - - /** - * Sets or gets the negative prefix and suffix. The default negative prefix is - * "−", and the default negative suffix is the empty string. - * - * @param {string} [x] the negative prefix. - * @param {string} [y] the negative suffix. - * @returns {pv.Format.number} this or the current negative format. - */ - format.negativeAffix = function(x, y) { - if (arguments.length) { - np = String(x || ""); - ns = String(y || ""); - return this; - } - return [np, ns]; - }; - - return format; -}; -(function(){ - - var _cache; - - pv.Text = {}; - - pv.Text.createCache = function(){ - return new FontSizeCache(); - }; - - pv.Text.usingCache = function(cache, fun, ctx){ - if(!(cache instanceof FontSizeCache)){ - throw new Error("Not a valid cache."); - } - - var prevCache = _cache; - - _cache = cache; - try{ - return fun.call(ctx); - } finally { - _cache = prevCache; - } - }; - - pv.Text.measure = function(text, font){ - if(text == null){ - text = ""; - } else { - text = "" + text; - } - - var bbox = _cache && _cache.get(font, text); - if(!bbox){ - if(!text){ - bbox = {width: 0, height: 0}; - } else { - bbox = this.measureCore(text, font); - } - - if(_cache){ - _cache.put(font, text, bbox); - } - } - - return bbox; - }; - - pv.Text.fontHeight = function(font){ - return pv.Text.measure('M', font).height; - }; - - // Replace with another custom implementation if necessary - pv.Text.measureCore = (function(){ - - // SVG implementation - var _svgText, _svgTextFont; - - function createTextSizePlaceholder(){ - var div = document.createElement('div'); - div.id = 'pvSVGText_' + new Date().getTime(); - - var style = div.style; - style.position = 'absolute'; - style.visibility = 'hidden'; - style.width = 0; - style.height = 0; - style.left = 0; - style.top = 0; - - document.body.appendChild(div); - - return div; - } - - return function(text, font){ - if(!_svgText){ - var holder = createTextSizePlaceholder(); - var svgElem = pv.SvgScene.create('svg'); - svgElem.setAttribute('font-size', '10px'); - svgElem.setAttribute('font-family', 'sans-serif'); - - _svgText = pv.SvgScene.create('text'); - svgElem.appendChild(_svgText); - - holder.appendChild(svgElem); - } - - if(!font){ - font = null; - } - - if(_svgTextFont !== font){ - _svgTextFont = font; - pv.SvgScene.setStyle(_svgText, {'font': font}); - } - - var textNode = _svgText.firstChild; - if(textNode) { - textNode.nodeValue = ''+text; - } else { - if (pv.renderer() === "svgweb") { - // SVGWeb needs an extra 'true' to create SVG text nodes properly in IE. - _svgText.appendChild(document.createTextNode(''+text, true)); - } else { - _svgText.appendChild(document.createTextNode(''+text)); - } - } - - var box = _svgText.getBBox(); - return {width: box.width, height: box.height}; - }; - }()); - - // -------- - - var FontSizeCache = function(){ - this._fontsCache = {}; - }; - - var hasOwnProp = Object.prototype.hasOwnProperty; - - FontSizeCache.prototype._getFont = function(font){ - font = font || ''; - return hasOwnProp.call(this._fontsCache, font) ? - this._fontsCache[font] : - (this._fontsCache[font] = {}); - }; - - FontSizeCache.prototype.get = function(font, text){ - text = text || ''; - - var fontCache = this._getFont(font); - return hasOwnProp.call(fontCache, text) ? - fontCache[text] : - null; - }; - - FontSizeCache.prototype.put = function(font, text, size){ - return this._getFont(font)[text||''] = size; - }; - -}());/** - * @private A private variant of Array.prototype.map that supports the index - * property. - */ -pv.map = function(array, f) { - var o = {}; - return f - ? array.map(function(d, i) { o.index = i; return f.call(o, d); }) - : array.slice(); -}; - -/** - * Concatenates the specified array with itself n times. For example, - * pv.repeat([1, 2]) returns [1, 2, 1, 2]. - * - * @param {array} a an array. - * @param {number} [n] the number of times to repeat; defaults to two. - * @returns {array} an array that repeats the specified array. - */ -pv.repeat = function(array, n) { - if (arguments.length == 1) n = 2; - return pv.blend(pv.range(n).map(function() { return array; })); -}; - -/** - * Creates an array of the specified length, - * and, optionally, initializes it with the specified default value. - * - * @param {number} [len] the length of the array; defaults to 0. - * @param {number} [dv] the default value with which to initialize each position; defaults to undefined. - * @returns {array} an array as specified. - */ -pv.array = function(len, dv){ - var a = len >= 0 ? new Array(len) : []; - if(dv !== undefined){ - for(var i = 0 ; i < len ; i++){ - a[i] = dv; - } - } - - return a; -}; - -/** - * Given two arrays a and b, returns an array of all possible - * pairs of elements [ai, bj]. The outer loop is on array - * a, while the inner loop is on b, such that the order of - * returned elements is [a0, b0], [a0, - * b1], ... [a0, bm], [a1, - * b0], [a1, b1], ... [a1, - * bm], ... [an, bm]. If either array is empty, - * an empty array is returned. - * - * @param {array} a an array. - * @param {array} b an array. - * @returns {array} an array of pairs of elements in a and b. - */ -pv.cross = function(a, b) { - var array = []; - for (var i = 0, n = a.length, m = b.length; i < n; i++) { - for (var j = 0, x = a[i]; j < m; j++) { - array.push([x, b[j]]); - } - } - return array; -}; - -/** - * Given the specified array of arrays, concatenates the arrays into a single - * array. If the individual arrays are explicitly known, an alternative to blend - * is to use JavaScript's concat method directly. These two equivalent - * expressions:

    - * - *
  • pv.blend([[1, 2, 3], ["a", "b", "c"]]) - *
  • [1, 2, 3].concat(["a", "b", "c"]) - * - *
return [1, 2, 3, "a", "b", "c"]. - * - * @param {array[]} arrays an array of arrays. - * @returns {array} an array containing all the elements of each array in - * arrays. - */ -pv.blend = function(arrays) { - return Array.prototype.concat.apply([], arrays); -}; - -/** - * Given the specified array of arrays, transposes each element - * arrayij with arrayji. If the array has dimensions - * n×m, it will have dimensions m×n - * after this method returns. This method transposes the elements of the array - * in place, mutating the array, and returning a reference to the array. - * - * @param {array[]} arrays an array of arrays. - * @returns {array[]} the passed-in array, after transposing the elements. - */ -pv.transpose = function(arrays) { - var n = arrays.length, m = pv.max(arrays, function(d) { return d.length; }); - - if (m > n) { - arrays.length = m; - for (var i = n; i < m; i++) { - arrays[i] = new Array(n); - } - for (var i = 0; i < n; i++) { - for (var j = i + 1; j < m; j++) { - var t = arrays[i][j]; - arrays[i][j] = arrays[j][i]; - arrays[j][i] = t; - } - } - } else { - for (var i = 0; i < m; i++) { - arrays[i].length = n; - } - for (var i = 0; i < n; i++) { - for (var j = 0; j < i; j++) { - var t = arrays[i][j]; - arrays[i][j] = arrays[j][i]; - arrays[j][i] = t; - } - } - } - - arrays.length = m; - for (var i = 0; i < m; i++) { - arrays[i].length = n; - } - - return arrays; -}; - -/** - * Returns a normalized copy of the specified array, such that the sum of the - * returned elements sum to one. If the specified array is not an array of - * numbers, an optional accessor function f can be specified to map the - * elements to numbers. For example, if array is an array of objects, - * and each object has a numeric property "foo", the expression - * - *
pv.normalize(array, function(d) d.foo)
- * - * returns a normalized array on the "foo" property. If an accessor function is - * not specified, the identity function is used. Accessor functions can refer to - * this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number[]} an array of numbers that sums to one. - */ -pv.normalize = function(array, f) { - var norm = pv.map(array, f), sum = pv.sum(norm); - for (var i = 0; i < norm.length; i++) norm[i] /= sum; - return norm; -}; - -/** - * Returns a permutation of the specified array, using the specified array of - * indexes. The returned array contains the corresponding element in - * array for each index in indexes, in order. For example, - * - *
pv.permute(["a", "b", "c"], [1, 2, 0])
- * - * returns ["b", "c", "a"]. It is acceptable for the array of indexes - * to be a different length from the array of elements, and for indexes to be - * duplicated or omitted. The optional accessor function f can be used - * to perform a simultaneous mapping of the array elements. Accessor functions - * can refer to this.index. - * - * @param {array} array an array. - * @param {number[]} indexes an array of indexes into array. - * @param {function} [f] an optional accessor function. - * @returns {array} an array of elements from array; a permutation. - */ -pv.permute = function(array, indexes, f) { - if (!f) f = pv.identity; - var p = new Array(indexes.length), o = {}; - indexes.forEach(function(j, i) { o.index = j; p[i] = f.call(o, array[j]); }); - return p; -}; - -/** - * Returns a map from key to index for the specified keys array. For - * example, - * - *
pv.numerate(["a", "b", "c"])
- * - * returns {a: 0, b: 1, c: 2}. Note that since JavaScript maps only - * support string keys, keys must contain strings, or other values that - * naturally map to distinct string values. Alternatively, an optional accessor - * function f can be specified to compute the string key for the given - * element. Accessor functions can refer to this.index. - * - * @param {array} keys an array, usually of string keys. - * @param {function} [f] an optional key function. - * @returns a map from key to index. - */ -pv.numerate = function(keys, f) { - if (!f) f = pv.identity; - var map = {}, o = {}; - keys.forEach(function(x, i) { o.index = i; map[f.call(o, x)] = i; }); - return map; -}; - -/** - * Returns the unique elements in the specified array, in the order they appear. - * Note that since JavaScript maps only support string keys, array must - * contain strings, or other values that naturally map to distinct string - * values. Alternatively, an optional accessor function f can be - * specified to compute the string key for the given element. Accessor functions - * can refer to this.index. - * - * @param {array} array an array, usually of string keys. - * @param {function} [f] an optional key function. - * @returns {array} the unique values. - */ -pv.uniq = function(array, f) { - if (!f) f = pv.identity; - var map = {}, keys = [], o = {}, y; - array.forEach(function(x, i) { - o.index = i; - y = f.call(o, x); - if (!(y in map)) map[y] = keys.push(y); - }); - return keys; -}; - -/** - * The comparator function for natural order. This can be used in conjunction with - * the built-in array sort method to sort elements by their natural - * order, ascending. Note that if no comparator function is specified to the - * built-in sort method, the default order is lexicographic, not - * natural! - * - * @see Array.sort. - * @param a an element to compare. - * @param b an element to compare. - * @returns {number} negative if a < b; positive if a > b; otherwise 0. - */ -pv.naturalOrder = function(a, b) { - return (a < b) ? -1 : ((a > b) ? 1 : 0); -}; - -/** - * The comparator function for reverse natural order. This can be used in - * conjunction with the built-in array sort method to sort elements by - * their natural order, descending. Note that if no comparator function is - * specified to the built-in sort method, the default order is - * lexicographic, not natural! - * - * @see #naturalOrder - * @param a an element to compare. - * @param b an element to compare. - * @returns {number} negative if a < b; positive if a > b; otherwise 0. - */ -pv.reverseOrder = function(b, a) { - return (a < b) ? -1 : ((a > b) ? 1 : 0); -}; - -/** - * Searches the specified array of numbers for the specified value using the - * binary search algorithm. The array must be sorted (as by the sort - * method) prior to making this call. If it is not sorted, the results are - * undefined. If the array contains multiple elements with the specified value, - * there is no guarantee which one will be found. - * - *

The insertion point is defined as the point at which the value - * would be inserted into the array: the index of the first element greater than - * the value, or array.length, if all elements in the array are less - * than the specified value. Note that this guarantees that the return value - * will be nonnegative if and only if the value is found. - * - * @param {number[]} array the array to be searched. - * @param {number} value the value to be searched for. - * @returns the index of the search value, if it is contained in the array; - * otherwise, (-(insertion point) - 1). - * @param {function} [f] an optional key function. - */ -pv.search = function(array, value, f) { - if (!f) f = pv.identity; - var low = 0, high = array.length - 1; - while (low <= high) { - var mid = (low + high) >> 1, midValue = f(array[mid]); - if (midValue < value) low = mid + 1; - else if (midValue > value) high = mid - 1; - else return mid; - } - return -low - 1; -}; - -pv.search.index = function(array, value, f) { - var i = pv.search(array, value, f); - return (i < 0) ? (-i - 1) : i; -}; -/** - * Returns an array of numbers, starting at start, incrementing by - * step, until stop is reached. The stop value is - * exclusive. If only a single argument is specified, this value is interpeted - * as the stop value, with the start value as zero. If only two - * arguments are specified, the step value is implied to be one. - * - *

The method is modeled after the built-in range method from - * Python. See the Python documentation for more details. - * - * @see Python range - * @param {number} [start] the start value. - * @param {number} stop the stop value. - * @param {number} [step] the step value. - * @returns {number[]} an array of numbers. - */ -pv.range = function(start, stop, step) { - if (arguments.length == 1) { - stop = start; - start = 0; - } - if (step == undefined) step = 1; - if ((stop - start) / step == Infinity) throw new Error("range must be finite"); - var array = [], i = 0, j; - stop -= (stop - start) * 1e-10; // floating point precision! - if (step < 0) { - while ((j = start + step * i++) > stop) { - array.push(j); - } - } else { - while ((j = start + step * i++) < stop) { - array.push(j); - } - } - return array; -}; - -/** - * Returns a random number in the range [start, stop) that is - * a multiple of step. More specifically, the returned number is of the - * form start + n * step, where n is a - * nonnegative integer. If step is not specified, it defaults to 1, - * returning a random integer if start is also an integer. - * - * @param {number} [start] the start value value. - * @param {number} stop the stop value. - * @param {number} [step] the step value. - * @returns {number} a random number between start and stop. - */ -pv.random = function(start, stop, step) { - if (arguments.length == 1) { - stop = start; - start = 0; - } - if (step == undefined) step = 1; - return step - ? (Math.floor(Math.random() * (stop - start) / step) * step + start) - : (Math.random() * (stop - start) + start); -}; - -/** - * Returns the sum of the specified array. If the specified array is not an - * array of numbers, an optional accessor function f can be specified - * to map the elements to numbers. See {@link #normalize} for an example. - * Accessor functions can refer to this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number} the sum of the specified array. - */ -pv.sum = function(array, f) { - var o = {}; - return array.reduce(f - ? function(p, d, i) { o.index = i; return p + f.call(o, d); } - : function(p, d) { return p + d; }, 0); -}; - -/** - * Returns the maximum value of the specified array. If the specified array is - * not an array of numbers, an optional accessor function f can be - * specified to map the elements to numbers. See {@link #normalize} for an - * example. Accessor functions can refer to this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number} the maximum value of the specified array. - */ -pv.max = function(array, f) { - if (f == pv.index) return array.length - 1; - return Math.max.apply(null, f ? pv.map(array, f) : array); -}; - -/** - * Returns the index of the maximum value of the specified array. If the - * specified array is not an array of numbers, an optional accessor function - * f can be specified to map the elements to numbers. See - * {@link #normalize} for an example. Accessor functions can refer to - * this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number} the index of the maximum value of the specified array. - */ -pv.max.index = function(array, f) { - if (!array.length) return -1; - if (f == pv.index) return array.length - 1; - if (!f) f = pv.identity; - var maxi = 0, maxx = -Infinity, o = {}; - for (var i = 0; i < array.length; i++) { - o.index = i; - var x = f.call(o, array[i]); - if (x > maxx) { - maxx = x; - maxi = i; - } - } - return maxi; -}; - -/** - * Returns the minimum value of the specified array of numbers. If the specified - * array is not an array of numbers, an optional accessor function f - * can be specified to map the elements to numbers. See {@link #normalize} for - * an example. Accessor functions can refer to this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number} the minimum value of the specified array. - */ -pv.min = function(array, f) { - if (f == pv.index) return 0; - return Math.min.apply(null, f ? pv.map(array, f) : array); -}; - -/** - * Returns the index of the minimum value of the specified array. If the - * specified array is not an array of numbers, an optional accessor function - * f can be specified to map the elements to numbers. See - * {@link #normalize} for an example. Accessor functions can refer to - * this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number} the index of the minimum value of the specified array. - */ -pv.min.index = function(array, f) { - if (!array.length) return -1; - if (f == pv.index) return 0; - if (!f) f = pv.identity; - var mini = 0, minx = Infinity, o = {}; - for (var i = 0; i < array.length; i++) { - o.index = i; - var x = f.call(o, array[i]); - if (x < minx) { - minx = x; - mini = i; - } - } - return mini; -}; - -/** - * Returns the arithmetic mean, or average, of the specified array. If the - * specified array is not an array of numbers, an optional accessor function - * f can be specified to map the elements to numbers. See - * {@link #normalize} for an example. Accessor functions can refer to - * this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number} the mean of the specified array. - */ -pv.mean = function(array, f) { - return pv.sum(array, f) / array.length; -}; - -/** - * Returns the median of the specified array. If the specified array is not an - * array of numbers, an optional accessor function f can be specified - * to map the elements to numbers. See {@link #normalize} for an example. - * Accessor functions can refer to this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number} the median of the specified array. - */ -pv.median = function(array, f) { - if (f == pv.index) return (array.length - 1) / 2; - array = pv.map(array, f).sort(pv.naturalOrder); - if (array.length % 2) return array[Math.floor(array.length / 2)]; - var i = array.length / 2; - return (array[i - 1] + array[i]) / 2; -}; - -/** - * Returns the unweighted variance of the specified array. If the specified - * array is not an array of numbers, an optional accessor function f - * can be specified to map the elements to numbers. See {@link #normalize} for - * an example. Accessor functions can refer to this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number} the variance of the specified array. - */ -pv.variance = function(array, f) { - if (array.length < 1) return NaN; - if (array.length == 1) return 0; - var mean = pv.mean(array, f), sum = 0, o = {}; - if (!f) f = pv.identity; - for (var i = 0; i < array.length; i++) { - o.index = i; - var d = f.call(o, array[i]) - mean; - sum += d * d; - } - return sum; -}; - -/** - * Returns an unbiased estimation of the standard deviation of a population, - * given the specified random sample. If the specified array is not an array of - * numbers, an optional accessor function f can be specified to map the - * elements to numbers. See {@link #normalize} for an example. Accessor - * functions can refer to this.index. - * - * @param {array} array an array of objects, or numbers. - * @param {function} [f] an optional accessor function. - * @returns {number} the standard deviation of the specified array. - */ -pv.deviation = function(array, f) { - return Math.sqrt(pv.variance(array, f) / (array.length - 1)); -}; - -/** - * Returns the logarithm with a given base value. - * - * @param {number} x the number for which to compute the logarithm. - * @param {number} b the base of the logarithm. - * @returns {number} the logarithm value. - */ -pv.log = function(x, b) { - return Math.log(x) / Math.log(b); -}; - -/** - * Computes a zero-symmetric logarithm. Computes the logarithm of the absolute - * value of the input, and determines the sign of the output according to the - * sign of the input value. - * - * @param {number} x the number for which to compute the logarithm. - * @param {number} b the base of the logarithm. - * @returns {number} the symmetric log value. - */ -pv.logSymmetric = function(x, b) { - return (x == 0) ? 0 : ((x < 0) ? -pv.log(-x, b) : pv.log(x, b)); -}; - -/** - * Computes a zero-symmetric logarithm, with adjustment to values between zero - * and the logarithm base. This adjustment introduces distortion for values less - * than the base number, but enables simultaneous plotting of log-transformed - * data involving both positive and negative numbers. - * - * @param {number} x the number for which to compute the logarithm. - * @param {number} b the base of the logarithm. - * @returns {number} the adjusted, symmetric log value. - */ -pv.logAdjusted = function(x, b) { - if (!isFinite(x)) return x; - var negative = x < 0; - if (x < b) x += (b - x) / b; - return negative ? -pv.log(x, b) : pv.log(x, b); -}; - -/** - * Rounds an input value down according to its logarithm. The method takes the - * floor of the logarithm of the value and then uses the resulting value as an - * exponent for the base value. - * - * @param {number} x the number for which to compute the logarithm floor. - * @param {number} b the base of the logarithm. - * @returns {number} the rounded-by-logarithm value. - */ -pv.logFloor = function(x, b) { - return (x > 0) - ? Math.pow(b, Math.floor(pv.log(x, b))) - : -Math.pow(b, -Math.floor(-pv.log(-x, b))); -}; - -/** - * Rounds an input value up according to its logarithm. The method takes the - * ceiling of the logarithm of the value and then uses the resulting value as an - * exponent for the base value. - * - * @param {number} x the number for which to compute the logarithm ceiling. - * @param {number} b the base of the logarithm. - * @returns {number} the rounded-by-logarithm value. - */ -pv.logCeil = function(x, b) { - return (x > 0) - ? Math.pow(b, Math.ceil(pv.log(x, b))) - : -Math.pow(b, -Math.ceil(-pv.log(-x, b))); -}; - -(function() { - var radians = Math.PI / 180, - degrees = 180 / Math.PI; - - /** Returns the number of radians corresponding to the specified degrees. */ - pv.radians = function(degrees) { return radians * degrees; }; - - /** Returns the number of degrees corresponding to the specified radians. */ - pv.degrees = function(radians) { return degrees * radians; }; -})(); -/** - * Returns all of the property names (keys) of the specified object (a map). The - * order of the returned array is not defined. - * - * @param map an object. - * @returns {string[]} an array of strings corresponding to the keys. - * @see #entries - */ -pv.keys = function(map) { - var array = []; - for (var key in map) { - array.push(key); - } - return array; -}; - -/** - * Returns all of the entries (key-value pairs) of the specified object (a - * map). The order of the returned array is not defined. Each key-value pair is - * represented as an object with key and value attributes, - * e.g., {key: "foo", value: 42}. - * - * @param map an object. - * @returns {array} an array of key-value pairs corresponding to the keys. - */ -pv.entries = function(map) { - var array = []; - for (var key in map) { - array.push({ key: key, value: map[key] }); - } - return array; -}; - -/** - * Returns all of the values (attribute values) of the specified object (a - * map). The order of the returned array is not defined. - * - * @param map an object. - * @returns {array} an array of objects corresponding to the values. - * @see #entries - */ -pv.values = function(map) { - var array = []; - for (var key in map) { - array.push(map[key]); - } - return array; -}; - -/** - * Returns a map constructed from the specified keys, using the - * function f to compute the value for each key. The single argument to - * the value function is the key. The callback is invoked only for indexes of - * the array which have assigned values; it is not invoked for indexes which - * have been deleted or which have never been assigned values. - * - *

For example, this expression creates a map from strings to string length: - * - *

pv.dict(["one", "three", "seventeen"], function(s) s.length)
- * - * The returned value is {one: 3, three: 5, seventeen: 9}. Accessor - * functions can refer to this.index. - * - * @param {array} keys an array. - * @param {function} f a value function. - * @returns a map from keys to values. - */ -pv.dict = function(keys, f) { - var m = {}, o = {}; - for (var i = 0; i < keys.length; i++) { - if (i in keys) { - var k = keys[i]; - o.index = i; - m[k] = f.call(o, k); - } - } - return m; -}; - -/** @private */ -pv.hasOwnProp = Object.prototype.hasOwnProperty; - -/** - * Copies own properties of b into a. - * - * @param {object} a the target object. - * @param {object} [b] the source object. - * @returns {object} the target object. - */ -pv.copyOwn = function(a, b){ - if(b){ - var hop = pv.hasOwnProp; - for(var p in b){ - if(hop.call(b, p)){ - a[p] = b[p]; - } - } - } - return a; -}; -/** - * Returns a {@link pv.Dom} operator for the given map. This is a convenience - * factory method, equivalent to new pv.Dom(map). To apply the operator - * and retrieve the root node, call {@link pv.Dom#root}; to retrieve all nodes - * flattened, use {@link pv.Dom#nodes}. - * - * @see pv.Dom - * @param map a map from which to construct a DOM. - * @returns {pv.Dom} a DOM operator for the specified map. - */ -pv.dom = function(map) { - return new pv.Dom(map); -}; - -/** - * Constructs a DOM operator for the specified map. This constructor should not - * be invoked directly; use {@link pv.dom} instead. - * - * @class Represets a DOM operator for the specified map. This allows easy - * transformation of a hierarchical JavaScript object (such as a JSON map) to a - * W3C Document Object Model hierarchy. For more information on which attributes - * and methods from the specification are supported, see {@link pv.Dom.Node}. - * - *

Leaves in the map are determined using an associated leaf function; - * see {@link #leaf}. By default, leaves are any value whose type is not - * "object", such as numbers or strings. - * - * @param map a map from which to construct a DOM. - */ -pv.Dom = function(map) { - this.$map = map; -}; - -/** @private The default leaf function. */ -pv.Dom.prototype.$leaf = function(n) { - return typeof n != "object"; -}; - -/** - * Sets or gets the leaf function for this DOM operator. The leaf function - * identifies which values in the map are leaves, and which are internal nodes. - * By default, objects are considered internal nodes, and primitives (such as - * numbers and strings) are considered leaves. - * - * @param {function} f the new leaf function. - * @returns the current leaf function, or this. - */ -pv.Dom.prototype.leaf = function(f) { - if (arguments.length) { - this.$leaf = f; - return this; - } - return this.$leaf; -}; - -/** - * Applies the DOM operator, returning the root node. - * - * @returns {pv.Dom.Node} the root node. - * @param {string} [nodeName] optional node name for the root. - */ -pv.Dom.prototype.root = function(nodeName) { - var leaf = this.$leaf, root = recurse(this.$map); - - /** @private */ - function recurse(map) { - var n = new pv.Dom.Node(); - for (var k in map) { - var v = map[k]; - n.appendChild(leaf(v) ? new pv.Dom.Node(v) : recurse(v)).nodeName = k; - } - return n; - } - - root.nodeName = nodeName; - return root; -}; - -/** - * Applies the DOM operator, returning the array of all nodes in preorder - * traversal. - * - * @returns {array} the array of nodes in preorder traversal. - */ -pv.Dom.prototype.nodes = function() { - return this.root().nodes(); -}; - -/** - * Constructs a DOM node for the specified value. Instances of this class are - * not typically created directly; instead they are generated from a JavaScript - * map using the {@link pv.Dom} operator. - * - * @class Represents a Node in the W3C Document Object Model. - */ -pv.Dom.Node = function(value) { - if(value !== undefined){ - this.nodeValue = value; - } - - this.childNodes = []; -}; - -/** - * The node name. When generated from a map, the node name corresponds to the - * key at the given level in the map. Note that the root node has no associated - * key, and thus has an undefined node name (and no parentNode). - * - * @type string - * @field pv.Dom.Node.prototype.nodeName - */ - -/** - * The node value. When generated from a map, node value corresponds to the leaf - * value for leaf nodes, and is undefined for internal nodes. - * - * @field pv.Dom.Node.prototype.nodeValue - */ -pv.Dom.Node.prototype.nodeValue = undefined; - -/** - * The array of child nodes. This array is empty for leaf nodes. An easy way to - * check if child nodes exist is to query firstChild. - * - * @type array - * @field pv.Dom.Node.prototype.childNodes - */ - -/** - * The parent node, which is null for root nodes. - * - * @type pv.Dom.Node - */ -pv.Dom.Node.prototype.parentNode = null; - -/** - * The first child, which is null for leaf nodes. - * - * @type pv.Dom.Node - */ -pv.Dom.Node.prototype.firstChild = null; - -/** - * The last child, which is null for leaf nodes. - * - * @type pv.Dom.Node - */ -pv.Dom.Node.prototype.lastChild = null; - -/** - * The previous sibling node, which is null for the first child. - * - * @type pv.Dom.Node - */ -pv.Dom.Node.prototype.previousSibling = null; - -/** - * The next sibling node, which is null for the last child. - * - * @type pv.Dom.Node - */ -pv.Dom.Node.prototype.nextSibling = null; - -/** - * The index of the first child - * whose {@link #_childIndex} is dirty. - * - * @private - * @type number | null - */ -pv.Dom.Node.prototype._firstDirtyChildIndex = Infinity; - -/** - * Removes the specified child node from this node. - * - * @throws Error if the specified child is not a child of this node. - * @returns {pv.Dom.Node} the removed child. - */ -pv.Dom.Node.prototype.removeChild = function(n) { - var i = this.childNodes.indexOf(n); - if (i === -1) throw new Error("child not found"); - - return this.removeAt(i); -}; - -/** - * Appends the specified child node to this node. If the specified child is - * already part of the DOM, the child is first removed before being added to - * this node. - * - * @returns {pv.Dom.Node} the appended child. - */ -pv.Dom.Node.prototype.appendChild = function(n){ - var pn = n.parentNode; - if (pn) pn.removeChild(n); - - var lc = this.lastChild; - n.parentNode = this; - n.previousSibling = lc; - if (lc) { - lc.nextSibling = n; - n._childIndex = lc._childIndex + 1; - } else { - this.firstChild = n; - n._childIndex = 0; - } - - this.lastChild = n; - this.childNodes.push(n); - - return n; -}; - -/** - * Inserts the specified child n before the given reference child - * r of this node. If r is null, this method is equivalent to - * {@link #appendChild}. If n is already part of the DOM, it is first - * removed before being inserted. - * - * @throws Error if r is non-null and not a child of this node. - * @returns {pv.Dom.Node} the inserted child. - */ -pv.Dom.Node.prototype.insertBefore = function(n, r){ - if (!r) return this.appendChild(n); - - var ns = this.childNodes; - var i = ns.indexOf(r); - if (i === -1) throw new Error("child not found"); - - return this.insertAt(n, i); -}; - -/** - * Inserts the specified child n at the given index. - * Any child from the given index onwards will be moved one position to the end. - * If i is null, this method is equivalent to - * {@link #appendChild}. - * If n is already part of the DOM, it is first - * removed before being inserted. - * - * @throws Error if i is non-null and greater than the current number of children. - * @returns {pv.Dom.Node} the inserted child. - */ -pv.Dom.Node.prototype.insertAt = function(n, i) { - if (i == null){ - return this.appendChild(n); - } - - var ns = this.childNodes; - var L = ns.length; - if (i === L){ - return this.appendChild(n); - } - - if(i > L){ - throw new Error("Index out of range."); - } - - var ni = i + 1; - var firstDirtyIndex = this._firstDirtyChildIndex; - if(ni < firstDirtyIndex){ - this._firstDirtyChildIndex = ni; - } - - var pn = n.parentNode; - if (pn) { - pn.removeChild(n); - } - - var r = ns[i]; - n.parentNode = this; - n.nextSibling = r; - n._childIndex = i; - - var psib = n.previousSibling = r.previousSibling; - if (psib) { - psib.nextSibling = n; - } else { - if (r === this.lastChild) { - this.lastChild = n; - } - this.firstChild = n; - } - - this.childNodes.splice(i, 0, n); - return n; -}; - -/** - * Removes the child node at the specified index from this node. - */ -pv.Dom.Node.prototype.removeAt = function(i) { - var ns = this.childNodes; - var n = ns[i]; - if(n){ - ns.splice(i, 1); - - if(i < ns.length){ - var firstDirtyIndex = this._firstDirtyChildIndex; - if(i < firstDirtyIndex){ - this._firstDirtyChildIndex = i; - } - } - - var psib = n.previousSibling; - if (psib) { - psib.nextSibling = n.nextSibling; - } else { - this.firstChild = n.nextSibling; - } - - var nsib = n.nextSibling; - if (nsib) { - nsib.previousSibling = n.previousSibling; - } else { - this.lastChild = n.previousSibling; - } - - delete n.nextSibling; - delete n.previousSibling; - delete n.parentNode; - } - - return n; -}; - -/** - * Replaces the specified child r of this node with the node n. If - * n is already part of the DOM, it is first removed before being added. - * - * @throws Error if r is not a child of this node. - */ -pv.Dom.Node.prototype.replaceChild = function(n, r) { - var ns = this.childNodes; - var i = ns.indexOf(r); - if (i === -1) throw new Error("child not found"); - - var pn = n.parentNode; - if (pn) pn.removeChild(n); - - n.parentNode = this; - n.nextSibling = r.nextSibling; - n._childIndex = r._childIndex; - - var psib = n.previousSibling = r.previousSibling; - if (psib) psib.nextSibling = n; - else this.firstChild = n; - - var nsib = r.nextSibling; - if (nsib) nsib.previousSibling = n; - else this.lastChild = n; - - ns[i] = n; - - return r; -}; - - -/** - * Obtains the child index of this node. - * Returns -1, if the node has no parent. - * - * @type number - */ -pv.Dom.Node.prototype.childIndex = function(){ - var p = this.parentNode; - if(p){ - var i = p._firstDirtyChildIndex; - if(i < Infinity){ - var ns = p.childNodes; - if(i < ns.length){ - for(var c = ns[i] ; c ; c = c.nextSibling){ - c._childIndex = i++; - } - } - - delete p._firstDirtyChildIndex; - } - - return this._childIndex; - } - - return -1; -}; - -/** - * Visits each node in the tree in preorder traversal, applying the specified - * function f. The arguments to the function are:

    - * - *
  1. The current node. - *
  2. The current depth, starting at 0 for the root node.
- * - * @param {function} f a function to apply to each node. - */ -pv.Dom.Node.prototype.visitBefore = function(f) { - function visit(n, i) { - f(n, i); - for (var c = n.firstChild; c; c = c.nextSibling) { - visit(c, i + 1); - } - } - visit(this, 0); -}; - -/** - * Visits each node in the tree in postorder traversal, applying the specified - * function f. The arguments to the function are:
    - * - *
  1. The current node. - *
  2. The current depth, starting at 0 for the root node.
- * - * @param {function} f a function to apply to each node. - */ -pv.Dom.Node.prototype.visitAfter = function(f) { - function visit(n, i) { - for (var c = n.firstChild; c; c = c.nextSibling) { - visit(c, i + 1); - } - f(n, i); - } - visit(this, 0); -}; - -/** - * Sorts child nodes of this node, and all descendent nodes recursively, using - * the specified comparator function f. The comparator function is - * passed two nodes to compare. - * - *

Note: during the sort operation, the comparator function should not rely - * on the tree being well-formed; the values of previousSibling and - * nextSibling for the nodes being compared are not defined during the - * sort operation. - * - * @param {function} f a comparator function. - * @returns this. - */ -pv.Dom.Node.prototype.sort = function(f) { - if (this.firstChild) { - delete p._firstDirtyChildIndex; - - this.childNodes.sort(f); - - var p = this.firstChild = this.childNodes[0], c; - delete p.previousSibling; - p._childIndex = 0; - - for (var i = 1; i < this.childNodes.length; i++) { - p.sort(f); - c = this.childNodes[i]; - c._childIndex = i; - c.previousSibling = p; - p = p.nextSibling = c; - } - - this.lastChild = p; - delete p.nextSibling; - - p.sort(f); - } - - return this; -}; - -/** - * Reverses all sibling nodes. - * - * @returns this. - */ -pv.Dom.Node.prototype.reverse = function() { - var childNodes = []; - this.visitAfter(function(n) { - while (n.lastChild) childNodes.push(n.removeChild(n.lastChild)); - for (var c; c = childNodes.pop();) n.insertBefore(c, n.firstChild); - }); - return this; -}; - -/** Returns all descendants of this node in preorder traversal. */ -pv.Dom.Node.prototype.nodes = function() { - var array = []; - - /** @private */ - function flatten(node) { - array.push(node); - node.childNodes.forEach(flatten); - } - - flatten(this, array); - return array; -}; - -/** - * Toggles the child nodes of this node. If this node is not yet toggled, this - * method removes all child nodes and appends them to a new toggled - * array attribute on this node. Otherwise, if this node is toggled, this method - * re-adds all toggled child nodes and deletes the toggled attribute. - * - *

This method has no effect if the node has no child nodes. - * - * @param {boolean} [recursive] whether the toggle should apply to descendants. - */ -pv.Dom.Node.prototype.toggle = function(recursive) { - if (recursive) return this.toggled - ? this.visitBefore(function(n) { if (n.toggled) n.toggle(); }) - : this.visitAfter(function(n) { if (!n.toggled) n.toggle(); }); - var n = this; - if (n.toggled) { - for (var c; c = n.toggled.pop();) n.appendChild(c); - delete n.toggled; - } else if (n.lastChild) { - n.toggled = []; - while (n.lastChild) n.toggled.push(n.removeChild(n.lastChild)); - } -}; - -/** - * Given a flat array of values, returns a simple DOM with each value wrapped by - * a node that is a child of the root node. - * - * @param {array} values. - * @returns {array} nodes. - */ -pv.nodes = function(values) { - var root = new pv.Dom.Node(); - for (var i = 0; i < values.length; i++) { - root.appendChild(new pv.Dom.Node(values[i])); - } - return root.nodes(); -}; -/** - * Returns a {@link pv.Tree} operator for the specified array. This is a - * convenience factory method, equivalent to new pv.Tree(array). - * - * @see pv.Tree - * @param {array} array an array from which to construct a tree. - * @returns {pv.Tree} a tree operator for the specified array. - */ -pv.tree = function(array) { - return new pv.Tree(array); -}; - -/** - * Constructs a tree operator for the specified array. This constructor should - * not be invoked directly; use {@link pv.tree} instead. - * - * @class Represents a tree operator for the specified array. The tree operator - * allows a hierarchical map to be constructed from an array; it is similar to - * the {@link pv.Nest} operator, except the hierarchy is derived dynamically - * from the array elements. - * - *

For example, given an array of size information for ActionScript classes: - * - *

{ name: "flare.flex.FlareVis", size: 4116 },
- * { name: "flare.physics.DragForce", size: 1082 },
- * { name: "flare.physics.GravityForce", size: 1336 }, ...
- * - * To facilitate visualization, it may be useful to nest the elements by their - * package hierarchy: - * - *
var tree = pv.tree(classes)
- *     .keys(function(d) d.name.split("."))
- *     .map();
- * - * The resulting tree is: - * - *
{ flare: {
- *     flex: {
- *       FlareVis: {
- *         name: "flare.flex.FlareVis",
- *         size: 4116 } },
- *     physics: {
- *       DragForce: {
- *         name: "flare.physics.DragForce",
- *         size: 1082 },
- *       GravityForce: {
- *         name: "flare.physics.GravityForce",
- *         size: 1336 } },
- *     ... } }
- * - * By specifying a value function, - * - *
var tree = pv.tree(classes)
- *     .keys(function(d) d.name.split("."))
- *     .value(function(d) d.size)
- *     .map();
- * - * we can further eliminate redundant data: - * - *
{ flare: {
- *     flex: {
- *       FlareVis: 4116 },
- *     physics: {
- *       DragForce: 1082,
- *       GravityForce: 1336 },
- *   ... } }
- * - * For visualizations with large data sets, performance improvements may be seen - * by storing the data in a tree format, and then flattening it into an array at - * runtime with {@link pv.Flatten}. - * - * @param {array} array an array from which to construct a tree. - */ -pv.Tree = function(array) { - this.array = array; -}; - -/** - * Assigns a keys function to this operator; required. The keys function - * returns an array of strings for each element in the associated - * array; these keys determine how the elements are nested in the tree. The - * returned keys should be unique for each element in the array; otherwise, the - * behavior of this operator is undefined. - * - * @param {function} k the keys function. - * @returns {pv.Tree} this. - */ -pv.Tree.prototype.keys = function(k) { - this.k = k; - return this; -}; - -/** - * Assigns a value function to this operator; optional. The value - * function specifies an optional transformation of the element in the array - * before it is inserted into the map. If no value function is specified, it is - * equivalent to using the identity function. - * - * @param {function} k the value function. - * @returns {pv.Tree} this. - */ -pv.Tree.prototype.value = function(v) { - this.v = v; - return this; -}; - -/** - * Returns a hierarchical map of values. The hierarchy is determined by the keys - * function; the values in the map are determined by the value function. - * - * @returns a hierarchical map of values. - */ -pv.Tree.prototype.map = function() { - var map = {}, o = {}; - for (var i = 0; i < this.array.length; i++) { - o.index = i; - var value = this.array[i], keys = this.k.call(o, value), node = map; - for (var j = 0; j < keys.length - 1; j++) { - node = node[keys[j]] || (node[keys[j]] = {}); - } - node[keys[j]] = this.v ? this.v.call(o, value) : value; - } - return map; -}; -/** - * Returns a {@link pv.Nest} operator for the specified array. This is a - * convenience factory method, equivalent to new pv.Nest(array). - * - * @see pv.Nest - * @param {array} array an array of elements to nest. - * @returns {pv.Nest} a nest operator for the specified array. - */ -pv.nest = function(array) { - return new pv.Nest(array); -}; - -/** - * Constructs a nest operator for the specified array. This constructor should - * not be invoked directly; use {@link pv.nest} instead. - * - * @class Represents a {@link Nest} operator for the specified array. Nesting - * allows elements in an array to be grouped into a hierarchical tree - * structure. The levels in the tree are specified by key functions. The - * leaf nodes of the tree can be sorted by value, while the internal nodes can - * be sorted by key. Finally, the tree can be returned either has a - * multidimensional array via {@link #entries}, or as a hierarchical map via - * {@link #map}. The {@link #rollup} routine similarly returns a map, collapsing - * the elements in each leaf node using a summary function. - * - *

For example, consider the following tabular data structure of Barley - * yields, from various sites in Minnesota during 1931-2: - * - *

{ yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm" },
- * { yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca" },
- * { yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris" }, ...
- * - * To facilitate visualization, it may be useful to nest the elements first by - * year, and then by variety, as follows: - * - *
var nest = pv.nest(yields)
- *     .key(function(d) d.year)
- *     .key(function(d) d.variety)
- *     .entries();
- * - * This returns a nested array. Each element of the outer array is a key-values - * pair, listing the values for each distinct key: - * - *
{ key: 1931, values: [
- *   { key: "Manchuria", values: [
- *       { yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm" },
- *       { yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca" },
- *       { yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris" },
- *       ...
- *     ] },
- *   { key: "Glabron", values: [
- *       { yield: 43.07, variety: "Glabron", year: 1931, site: "University Farm" },
- *       { yield: 55.20, variety: "Glabron", year: 1931, site: "Waseca" },
- *       ...
- *     ] },
- *   ] },
- * { key: 1932, values: ... }
- * - * Further details, including sorting and rollup, is provided below on the - * corresponding methods. - * - * @param {array} array an array of elements to nest. - */ -pv.Nest = function(array) { - this.array = array; - this.keys = []; -}; - -/** - * Nests using the specified key function. Multiple keys may be added to the - * nest; the array elements will be nested in the order keys are specified. - * - * @param {function} key a key function; must return a string or suitable map - * key. - * @returns {pv.Nest} this. - */ -pv.Nest.prototype.key = function(key) { - this.keys.push(key); - return this; -}; - -/** - * Sorts the previously-added keys. The natural sort order is used by default - * (see {@link pv.naturalOrder}); if an alternative order is desired, - * order should be a comparator function. If this method is not called - * (i.e., keys are unsorted), keys will appear in the order they appear - * in the underlying elements array. For example, - * - *
pv.nest(yields)
- *     .key(function(d) d.year)
- *     .key(function(d) d.variety)
- *     .sortKeys()
- *     .entries()
- * - * groups yield data by year, then variety, and sorts the variety groups - * lexicographically (since the variety attribute is a string). - * - *

Key sort order is only used in conjunction with {@link #entries}, which - * returns an array of key-values pairs. If the nest is used to construct a - * {@link #map} instead, keys are unsorted. - * - * @param {function} [order] an optional comparator function. - * @returns {pv.Nest} this. - */ -pv.Nest.prototype.sortKeys = function(order) { - this.keys[this.keys.length - 1].order = order || pv.naturalOrder; - return this; -}; - -/** - * Sorts the leaf values. The natural sort order is used by default (see - * {@link pv.naturalOrder}); if an alternative order is desired, order - * should be a comparator function. If this method is not called (i.e., values - * are unsorted), values will appear in the order they appear in the - * underlying elements array. For example, - * - *

pv.nest(yields)
- *     .key(function(d) d.year)
- *     .key(function(d) d.variety)
- *     .sortValues(function(a, b) a.yield - b.yield)
- *     .entries()
- * - * groups yield data by year, then variety, and sorts the values for each - * variety group by yield. - * - *

Value sort order, unlike keys, applies to both {@link #entries} and - * {@link #map}. It has no effect on {@link #rollup}. - * - * @param {function} [order] an optional comparator function. - * @returns {pv.Nest} this. - */ -pv.Nest.prototype.sortValues = function(order) { - this.order = order || pv.naturalOrder; - return this; -}; - -/** - * Returns a hierarchical map of values. Each key adds one level to the - * hierarchy. With only a single key, the returned map will have a key for each - * distinct value of the key function; the correspond value with be an array of - * elements with that key value. If a second key is added, this will be a nested - * map. For example: - * - *

pv.nest(yields)
- *     .key(function(d) d.variety)
- *     .key(function(d) d.site)
- *     .map()
- * - * returns a map m such that m[variety][site] is an array, a subset of - * yields, with each element having the given variety and site. - * - * @returns a hierarchical map of values. - */ -pv.Nest.prototype.map = function() { - var map = {}, values = []; - - /* Build the map. */ - for (var i, j = 0; j < this.array.length; j++) { - var x = this.array[j]; - var m = map; - for (i = 0; i < this.keys.length - 1; i++) { - var k = this.keys[i](x); - if (!m[k]) m[k] = {}; - m = m[k]; - } - k = this.keys[i](x); - if (!m[k]) { - var a = []; - values.push(a); - m[k] = a; - } - m[k].push(x); - } - - /* Sort each leaf array. */ - if (this.order) { - for (var i = 0; i < values.length; i++) { - values[i].sort(this.order); - } - } - - return map; -}; - -/** - * Returns a hierarchical nested array. This method is similar to - * {@link pv.entries}, but works recursively on the entire hierarchy. Rather - * than returning a map like {@link #map}, this method returns a nested - * array. Each element of the array has a key and values - * field. For leaf nodes, the values array will be a subset of the - * underlying elements array; for non-leaf nodes, the values array will - * contain more key-values pairs. - * - *

For an example usage, see the {@link Nest} constructor. - * - * @returns a hierarchical nested array. - */ -pv.Nest.prototype.entries = function() { - - /** Recursively extracts the entries for the given map. */ - function entries(map) { - var array = []; - for (var k in map) { - var v = map[k]; - array.push({ key: k, values: (v instanceof Array) ? v : entries(v) }); - }; - return array; - } - - /** Recursively sorts the values for the given key-values array. */ - function sort(array, i) { - var o = this.keys[i].order; - if (o) array.sort(function(a, b) { return o(a.key, b.key); }); - if (++i < this.keys.length) { - for (var j = 0; j < array.length; j++) { - sort.call(this, array[j].values, i); - } - } - return array; - } - - return sort.call(this, entries(this.map()), 0); -}; - -/** - * Returns a rollup map. The behavior of this method is the same as - * {@link #map}, except that the leaf values are replaced with the return value - * of the specified rollup function f. For example, - * - *

pv.nest(yields)
- *      .key(function(d) d.site)
- *      .rollup(function(v) pv.median(v, function(d) d.yield))
- * - * first groups yield data by site, and then returns a map from site to median - * yield for the given site. - * - * @see #map - * @param {function} f a rollup function. - * @returns a hierarchical map, with the leaf values computed by f. - */ -pv.Nest.prototype.rollup = function(f) { - - /** Recursively descends to the leaf nodes (arrays) and does rollup. */ - function rollup(map) { - for (var key in map) { - var value = map[key]; - if (value instanceof Array) { - map[key] = f(value); - } else { - rollup(value); - } - } - return map; - } - - return rollup(this.map()); -}; -/** - * Returns a {@link pv.Flatten} operator for the specified map. This is a - * convenience factory method, equivalent to new pv.Flatten(map). - * - * @see pv.Flatten - * @param map a map to flatten. - * @returns {pv.Flatten} a flatten operator for the specified map. - */ -pv.flatten = function(map) { - return new pv.Flatten(map); -}; - -/** - * Constructs a flatten operator for the specified map. This constructor should - * not be invoked directly; use {@link pv.flatten} instead. - * - * @class Represents a flatten operator for the specified array. Flattening - * allows hierarchical maps to be flattened into an array. The levels in the - * input tree are specified by key functions. - * - *

For example, consider the following hierarchical data structure of Barley - * yields, from various sites in Minnesota during 1931-2: - * - *

{ 1931: {
- *     Manchuria: {
- *       "University Farm": 27.00,
- *       "Waseca": 48.87,
- *       "Morris": 27.43,
- *       ... },
- *     Glabron: {
- *       "University Farm": 43.07,
- *       "Waseca": 55.20,
- *       ... } },
- *   1932: {
- *     ... } }
- * - * To facilitate visualization, it may be useful to flatten the tree into a - * tabular array: - * - *
var array = pv.flatten(yields)
- *     .key("year")
- *     .key("variety")
- *     .key("site")
- *     .key("yield")
- *     .array();
- * - * This returns an array of object elements. Each element in the array has - * attributes corresponding to this flatten operator's keys: - * - *
{ site: "University Farm", variety: "Manchuria", year: 1931, yield: 27 },
- * { site: "Waseca", variety: "Manchuria", year: 1931, yield: 48.87 },
- * { site: "Morris", variety: "Manchuria", year: 1931, yield: 27.43 },
- * { site: "University Farm", variety: "Glabron", year: 1931, yield: 43.07 },
- * { site: "Waseca", variety: "Glabron", year: 1931, yield: 55.2 }, ...
- * - *

The flatten operator is roughly the inverse of the {@link pv.Nest} and - * {@link pv.Tree} operators. - * - * @param map a map to flatten. - */ -pv.Flatten = function(map) { - this.map = map; - this.keys = []; -}; - -/** - * Flattens using the specified key function. Multiple keys may be added to the - * flatten; the tiers of the underlying tree must correspond to the specified - * keys, in order. The order of the returned array is undefined; however, you - * can easily sort it. - * - * @param {string} key the key name. - * @param {function} [f] an optional value map function. - * @returns {pv.Nest} this. - */ -pv.Flatten.prototype.key = function(key, f) { - this.keys.push({name: key, value: f}); - delete this.$leaf; - return this; -}; - -/** - * Flattens using the specified leaf function. This is an alternative to - * specifying an explicit set of keys; the tiers of the underlying tree will be - * determined dynamically by recursing on the values, and the resulting keys - * will be stored in the entries keys attribute. The leaf function must - * return true for leaves, and false for internal nodes. - * - * @param {function} f a leaf function. - * @returns {pv.Nest} this. - */ -pv.Flatten.prototype.leaf = function(f) { - this.keys.length = 0; - this.$leaf = f; - return this; -}; - -/** - * Returns the flattened array. Each entry in the array is an object; each - * object has attributes corresponding to this flatten operator's keys. - * - * @returns an array of elements from the flattened map. - */ -pv.Flatten.prototype.array = function() { - var entries = [], stack = [], keys = this.keys, leaf = this.$leaf; - - /* Recursively visit using the leaf function. */ - if (leaf) { - function recurse(value, i) { - if (leaf(value)) { - entries.push({keys: stack.slice(), value: value}); - } else { - for (var key in value) { - stack.push(key); - recurse(value[key], i + 1); - stack.pop(); - } - } - } - recurse(this.map, 0); - return entries; - } - - /* Recursively visits the specified value. */ - function visit(value, i) { - if (i < keys.length - 1) { - for (var key in value) { - stack.push(key); - visit(value[key], i + 1); - stack.pop(); - } - } else { - entries.push(stack.concat(value)); - } - } - - visit(this.map, 0); - return entries.map(function(stack) { - var m = {}; - for (var i = 0; i < keys.length; i++) { - var k = keys[i], v = stack[i]; - m[k.name] = k.value ? k.value.call(null, v) : v; - } - return m; - }); -}; -/** - * Returns a new identity transform. - * - * @class Represents a transformation matrix. The transformation matrix is - * limited to expressing translate and uniform scale transforms only; shearing, - * rotation, general affine, and other transforms are not supported. - * - *

The methods on this class treat the transform as immutable, returning a - * copy of the transformation matrix with the specified transform applied. Note, - * alternatively, that the matrix fields can be get and set directly. - */ -pv.Transform = function() {}; -pv.Transform.prototype = {k: 1, x: 0, y: 0}; - -/** - * The scale magnitude; defaults to 1. - * - * @type number - * @name pv.Transform.prototype.k - */ - -/** - * The x-offset; defaults to 0. - * - * @type number - * @name pv.Transform.prototype.x - */ - -/** - * The y-offset; defaults to 0. - * - * @type number - * @name pv.Transform.prototype.y - */ - -/** - * @private The identity transform. - * - * @type pv.Transform - */ -pv.Transform.identity = new pv.Transform(); - -// k 0 x 1 0 a k 0 ka+x -// 0 k y * 0 1 b = 0 k kb+y -// 0 0 1 0 0 1 0 0 1 - -/** - * Returns a translated copy of this transformation matrix. - * - * @param {number} x the x-offset. - * @param {number} y the y-offset. - * @returns {pv.Transform} the translated transformation matrix. - */ -pv.Transform.prototype.translate = function(x, y) { - var v = new pv.Transform(); - v.k = this.k; - v.x = this.k * x + this.x; - v.y = this.k * y + this.y; - return v; -}; - -// k 0 x d 0 0 kd 0 x -// 0 k y * 0 d 0 = 0 kd y -// 0 0 1 0 0 1 0 0 1 - -/** - * Returns a scaled copy of this transformation matrix. - * - * @param {number} k - * @returns {pv.Transform} the scaled transformation matrix. - */ -pv.Transform.prototype.scale = function(k) { - var v = new pv.Transform(); - v.k = this.k * k; - v.x = this.x; - v.y = this.y; - return v; -}; - -/** - * Returns the inverse of this transformation matrix. - * - * @returns {pv.Transform} the inverted transformation matrix. - */ -pv.Transform.prototype.invert = function() { - var v = new pv.Transform(), k = 1 / this.k; - v.k = k; - v.x = -this.x * k; - v.y = -this.y * k; - return v; -}; - -// k 0 x d 0 a kd 0 ka+x -// 0 k y * 0 d b = 0 kd kb+y -// 0 0 1 0 0 1 0 0 1 - -/** - * Returns this matrix post-multiplied by the specified matrix m. - * - * @param {pv.Transform} m - * @returns {pv.Transform} the post-multiplied transformation matrix. - */ -pv.Transform.prototype.times = function(m) { - var v = new pv.Transform(); - v.k = this.k * m.k; - v.x = this.k * m.x + this.x; - v.y = this.k * m.y + this.y; - return v; -}; -/** - * Abstract; see the various scale implementations. - * - * @class Represents a scale; a function that performs a transformation from - * data domain to visual range. For quantitative and quantile scales, the domain - * is expressed as numbers; for ordinal scales, the domain is expressed as - * strings (or equivalently objects with unique string representations). The - * "visual range" may correspond to pixel space, colors, font sizes, and the - * like. - * - *

Note that scales are functions, and thus can be used as properties - * directly, assuming that the data associated with a mark is a number. While - * this is convenient for single-use scales, frequently it is desirable to - * define scales globally: - * - *

var y = pv.Scale.linear(0, 100).range(0, 640);
- * - * The y scale can now be equivalently referenced within a property: - * - *
    .height(function(d) y(d))
- * - * Alternatively, if the data are not simple numbers, the appropriate value can - * be passed to the y scale (e.g., d.foo). The {@link #by} - * method similarly allows the data to be mapped to a numeric value before - * performing the linear transformation. - * - * @see pv.Scale.quantitative - * @see pv.Scale.quantile - * @see pv.Scale.ordinal - * @extends function - */ -pv.Scale = function() {}; - -/** - * @private Returns a function that interpolators from the start value to the - * end value, given a parameter t in [0, 1]. - * - * @param start the start value. - * @param end the end value. - */ -pv.Scale.interpolator = function(start, end) { - if (typeof start == "number") { - return function(t) { - return t * (end - start) + start; - }; - } - - /* For now, assume color. */ - - // Gradients are not supported in animations - // Just show the first one if < 0.5 and the other if >= 0.5 - var startGradient = (start.type && start.type !== 'solid'); - var endGradient = (end.type && end .type !== 'solid'); - if (startGradient || endGradient) { - start = startGradient ? start : pv.color(start).rgb(); - end = endGradient ? end : pv.color(end ).rgb(); - return function(t){ - return t < 0.5 ? start : end; - }; - } - - start = pv.color(start).rgb(); - end = pv.color(end ).rgb(); - return function(t) { - var a = start.a * (1 - t) + end.a * t; - if (a < 1e-5) a = 0; // avoid scientific notation - return (start.a == 0) ? pv.rgb(end.r, end.g, end.b, a) - : ((end.a == 0) ? pv.rgb(start.r, start.g, start.b, a) - : pv.rgb( - Math.round(start.r * (1 - t) + end.r * t), - Math.round(start.g * (1 - t) + end.g * t), - Math.round(start.b * (1 - t) + end.b * t), a)); - }; -}; - -/** - * Returns a view of this scale by the specified accessor function f. - * Given a scale y, y.by(function(d) d.foo) is equivalent to - * function(d) y(d.foo). - * - *

This method is provided for convenience, such that scales can be - * succinctly defined inline. For example, given an array of data elements that - * have a score attribute with the domain [0, 1], the height property - * could be specified as: - * - *

    .height(pv.Scale.linear().range(0, 480).by(function(d) d.score))
- * - * This is equivalent to: - * - *
    .height(function(d) d.score * 480)
- * - * This method should be used judiciously; it is typically more clear to invoke - * the scale directly, passing in the value to be scaled. - * - * @function - * @name pv.Scale.prototype.by - * @param {function} f an accessor function. - * @returns {pv.Scale} a view of this scale by the specified accessor function. - */ - -pv.Scale.common = { - by: function(f) { - var scale = this; - function by() { return scale(f.apply(this, arguments)); } - for (var method in scale) by[method] = scale[method]; - return by; - }, - - by1: function(f) { - var scale = this; - function by1(x) { return scale(f.call(this, x)); } - for (var method in scale) by1[method] = scale[method]; - return by1; - }, - - transform: function(t){ - var scale = this; - function transfScale(){ - return t.call(this, scale.apply(scale, arguments)); - } - - for (var method in scale) transfScale[method] = scale[method]; - - return transfScale; - } -}; -/** - * Returns a default quantitative, linear, scale for the specified domain. The - * arguments to this constructor are optional, and equivalent to calling - * {@link #domain}. The default domain and range are [0,1]. - * - *

This constructor is typically not used directly; see one of the - * quantitative scale implementations instead. - * - * @class Represents an abstract quantitative scale; a function that performs a - * numeric transformation. This class is typically not used directly; see one of - * the quantitative scale implementations (linear, log, root, etc.) - * instead. A quantitative - * scale represents a 1-dimensional transformation from a numeric domain of - * input data [d0, d1] to a numeric range of - * pixels [r0, r1]. In addition to - * readability, scales offer several useful features: - * - *

1. The range can be expressed in colors, rather than pixels. For example: - * - *

    .fillStyle(pv.Scale.linear(0, 100).range("red", "green"))
- * - * will fill the marks "red" on an input value of 0, "green" on an input value - * of 100, and some color in-between for intermediate values. - * - *

2. The domain and range can be subdivided for a non-uniform - * transformation. For example, you may want a diverging color scale that is - * increasingly red for negative values, and increasingly green for positive - * values: - * - *

    .fillStyle(pv.Scale.linear(-1, 0, 1).range("red", "white", "green"))
- * - * The domain can be specified as a series of n monotonically-increasing - * values; the range must also be specified as n values, resulting in - * n - 1 contiguous linear scales. - * - *

3. Quantitative scales can be inverted for interaction. The - * {@link #invert} method takes a value in the output range, and returns the - * corresponding value in the input domain. This is frequently used to convert - * the mouse location (see {@link pv.Mark#mouse}) to a value in the input - * domain. Note that inversion is only supported for numeric ranges, and not - * colors. - * - *

4. A scale can be queried for reasonable "tick" values. The {@link #ticks} - * method provides a convenient way to get a series of evenly-spaced rounded - * values in the input domain. Frequently these are used in conjunction with - * {@link pv.Rule} to display tick marks or grid lines. - * - *

5. A scale can be "niced" to extend the domain to suitable rounded - * numbers. If the minimum and maximum of the domain are messy because they are - * derived from data, you can use {@link #nice} to round these values down and - * up to even numbers. - * - * @param {number...} domain... optional domain values. - * @see pv.Scale.linear - * @see pv.Scale.log - * @see pv.Scale.root - * @extends pv.Scale - */ -pv.Scale.quantitative = function() { - var d = [0, 1], // default domain - l = [0, 1], // default transformed domain - r = [0, 1], // default range - i = [pv.identity], // default interpolators - type = Number, // default type - n = false, // whether the domain is negative - f = pv.identity, // default forward transform - g = pv.identity, // default inverse transform - tickFormat = String, // default tick formatting function - tickFormatter = null, // custom tick formatting function - dateTickFormat, //custom date tick format - dateTickPrecision, //custom date tick precision - usedDateTickPrecision, - usedNumberExponent; - - /** @private */ - function newDate(x) { - return new Date(x); - } - - /** @private */ - function scale(x) { - var j = pv.search(d, x); - if (j < 0) j = -j - 2; - j = Math.max(0, Math.min(i.length - 1, j)); - return i[j]((f(x) - l[j]) / (l[j + 1] - l[j])); - } - - /** @private */ - scale.transform = function(forward, inverse) { - /** @ignore */ f = function(x) { return n ? -forward(-x) : forward(x); }; - /** @ignore */ g = function(y) { return n ? -inverse(-y) : inverse(y); }; - l = d.map(f); - return this; - }; - - /** - * Sets or gets the input domain. This method can be invoked several ways: - * - *

1. domain(min, ..., max) - * - *

Specifying the domain as a series of numbers is the most explicit and - * recommended approach. Most commonly, two numbers are specified: the minimum - * and maximum value. However, for a diverging scale, or other subdivided - * non-uniform scales, multiple values can be specified. Values can be derived - * from data using {@link pv.min} and {@link pv.max}. For example: - * - *

    .domain(0, pv.max(array))
- * - * An alternative method for deriving minimum and maximum values from data - * follows. - * - *

2. domain(array, minf, maxf) - * - *

When both the minimum and maximum value are derived from data, the - * arguments to the domain method can be specified as the array of - * data, followed by zero, one or two accessor functions. For example, if the - * array of data is just an array of numbers: - * - *

    .domain(array)
- * - * On the other hand, if the array elements are objects representing stock - * values per day, and the domain should consider the stock's daily low and - * daily high: - * - *
    .domain(array, function(d) d.low, function(d) d.high)
- * - * The first method of setting the domain is preferred because it is more - * explicit; setting the domain using this second method should be used only - * if brevity is required. - * - *

3. domain() - * - *

Invoking the domain method with no arguments returns the - * current domain as an array of numbers. - * - * @function - * @name pv.Scale.quantitative.prototype.domain - * @param {number...} domain... domain values. - * @returns {pv.Scale.quantitative} this, or the current domain. - */ - scale.domain = function(array, min, max) { - if (arguments.length) { - var o; // the object we use to infer the domain type - if (array instanceof Array) { - if (arguments.length < 2) min = pv.identity; - if (arguments.length < 3) max = min; - o = array.length && min(array[0]); - d = array.length ? [pv.min(array, min), pv.max(array, max)] : []; - } else { - o = array; - d = Array.prototype.slice.call(arguments).map(Number); - } - if (!d.length) d = [-Infinity, Infinity]; - else if (d.length == 1) d = [d[0], d[0]]; - n = (d[0] || d[d.length - 1]) < 0; - l = d.map(f); - type = (o instanceof Date) ? newDate : Number; - return this; - } - return d.map(type); - }; - - /** - * Sets or gets the output range. This method can be invoked several ways: - * - *

1. range(min, ..., max) - * - *

The range may be specified as a series of numbers or colors. Most - * commonly, two numbers are specified: the minimum and maximum pixel values. - * For a color scale, values may be specified as {@link pv.Color}s or - * equivalent strings. For a diverging scale, or other subdivided non-uniform - * scales, multiple values can be specified. For example: - * - *

    .range("red", "white", "green")
- * - *

Currently, only numbers and colors are supported as range values. The - * number of range values must exactly match the number of domain values, or - * the behavior of the scale is undefined. - * - *

2. range() - * - *

Invoking the range method with no arguments returns the current - * range as an array of numbers or colors. - * - * @function - * @name pv.Scale.quantitative.prototype.range - * @param {...} range... range values. - * @returns {pv.Scale.quantitative} this, or the current range. - */ - scale.range = function() { - if (arguments.length) { - r = Array.prototype.slice.call(arguments); - if (!r.length) r = [-Infinity, Infinity]; - else if (r.length == 1) r = [r[0], r[0]]; - i = []; - for (var j = 0; j < r.length - 1; j++) { - i.push(pv.Scale.interpolator(r[j], r[j + 1])); - } - return this; - } - return r; - }; - - /** - * Inverts the specified value in the output range, returning the - * corresponding value in the input domain. This is frequently used to convert - * the mouse location (see {@link pv.Mark#mouse}) to a value in the input - * domain. Inversion is only supported for numeric ranges, and not colors. - * - *

Note that this method does not do any rounding or bounds checking. If - * the input domain is discrete (e.g., an array index), the returned value - * should be rounded. If the specified y value is outside the range, - * the returned value may be equivalently outside the input domain. - * - * @function - * @name pv.Scale.quantitative.prototype.invert - * @param {number} y a value in the output range (a pixel location). - * @returns {number} a value in the input domain. - */ - scale.invert = function(y) { - var j = pv.search(r, y); - if (j < 0) j = -j - 2; - j = Math.max(0, Math.min(i.length - 1, j)); - return type(g(l[j] + (y - r[j]) / (r[j + 1] - r[j]) * (l[j + 1] - l[j]))); - }; - - /** - * Returns an array of evenly-spaced, suitably-rounded values in the input - * domain. This method attempts to return between 5 and 10 tick values. These - * values are frequently used in conjunction with {@link pv.Rule} to display - * tick marks or grid lines. - * - * @function - * @name pv.Scale.quantitative.prototype.ticks - * @param {number} [m] optional number of desired numeric ticks. - * @param {object} [options] optional keyword arguments object. - * @param {boolean} [options.roundInside=true] should the ticks be ensured to be strictly inside the scale domain, or to strictly outside the scale domain. - * @param {boolean} [options.numberExponentMin=-Inifinity] minimum value for the step exponent. - * @param {boolean} [options.numberExponentMax=+Inifinity] maximum value for the step exponent. - * @returns {number[]} an array input domain values to use as ticks. - */ - scale.ticks = function(m, options) { - var start = d[0], - end = d[d.length - 1], - reverse = end < start, - min = reverse ? end : start, - max = reverse ? start : end, - span = max - min; - - /* Special case: empty, invalid or infinite span. */ - if (!span || !isFinite(span)) { - if (type == newDate) tickFormat = pv.Format.date("%x"); - return [type(min)]; - } - - /* Special case: dates. */ - if (type == newDate) { - /* Floor the date d given the precision p. */ - function floor(d, p) { - switch (p) { - case 31536e6: d.setMonth(0); - case 2592e6: d.setDate(1); - case 6048e5: if (p == 6048e5) d.setDate(d.getDate() - d.getDay()); - case 864e5: d.setHours(0); - case 36e5: d.setMinutes(0); - case 6e4: d.setSeconds(0); - case 1e3: d.setMilliseconds(0); - } - } - - var nn = 5; - - var precision, format, increment, step = 1; - if (span >= nn * 31536e6) { - precision = 31536e6; - format = "%Y"; - /** @ignore */ increment = function(d) { d.setFullYear(d.getFullYear() + step); }; - } else if (span >= nn * 2592e6) { - precision = 2592e6; - format = "%m/%Y"; - /** @ignore */ increment = function(d) { d.setMonth(d.getMonth() + step); }; - } else if (span >= nn * 6048e5) { - precision = 6048e5; - format = "%m/%d"; - /** @ignore */ increment = function(d) { d.setDate(d.getDate() + 7 * step); }; - } else if (span >= nn * 864e5) { - precision = 864e5; - format = "%m/%d"; - /** @ignore */ increment = function(d) { d.setDate(d.getDate() + step); }; - } else if (span >= nn * 36e5) { - precision = 36e5; - format = "%I:%M %p"; - /** @ignore */ increment = function(d) { d.setHours(d.getHours() + step); }; - } else if (span >= nn * 6e4) { - precision = 6e4; - format = "%I:%M %p"; - /** @ignore */ increment = function(d) { d.setMinutes(d.getMinutes() + step); }; - } else if (span >= nn * 1e3) { - precision = 1e3; - format = "%I:%M:%S"; - /** @ignore */ increment = function(d) { d.setSeconds(d.getSeconds() + step); }; - } else { - precision = 1; - format = "%S.%Qs"; - /** @ignore */ increment = function(d) { d.setTime(d.getTime() + step); }; - } - - precision = dateTickPrecision ? dateTickPrecision : precision; - format = dateTickFormat ? dateTickFormat : format; - - usedDateTickPrecision = precision; - - tickFormat = pv.Format.date(format); - - var date = new Date(min), dates = []; - floor(date, precision); - - /* If we'd generate too many ticks, skip some!. */ - var n = span / precision; - if (n > 10) { - switch (precision) { - // 1 hour - case 36e5: { - step = (n > 20) ? 6 : 3; - date.setHours(Math.floor(date.getHours() / step) * step); - break; - } - - // 30 days - case 2592e6: { - step = (n > 24) ? 3 : ((n > 12) ? 2 : 1); - date.setMonth(Math.floor(date.getMonth() / step) * step); - break; - } - - // 7 day - // (nn = 5: - // span >= 35 days (n >= 5) - // span < 150 days (n < ~21.43) - case 6048e5: { - // span (days) | n (ticks/weeks) | step | new n | description - // ----------------------------------------------------------------- - // 106 - 149 | 15 - 22 | 3*7 = 21 | 5 - 7 | 15 weeks, ~3 months - // 71 - 105 | 11 - 15 | 2*7 = 14 | 5 - 7 | 11 weeks, ~2.2 months - // 35 - 70 | 5 - 10 | 1*7 = 7 | - | 5 weeks, ~1 month - step = (n > 15) ? 3 : (n > 10 ? 2 : 1); - date.setDate(Math.floor(date.getDate() / (7 * step)) * (7 * step)); - break; - } - - // 1 day (nn = 5: span >= 5 hours and span < 35 days) - // span > 10 days: more than 10 ticks - case 864e5: { - step = (n >= 30) ? 5 : ((n >= 15) ? 3 : 2); - date.setDate(Math.floor(date.getDate() / step) * step); - break; - } - - // 1 minute - case 6e4: { - step = (n > 30) ? 15 : ((n > 15) ? 10 : 5); - date.setMinutes(Math.floor(date.getMinutes() / step) * step); - break; - } - - // 1 second - case 1e3: { - step = (n > 90) ? 15 : ((n > 60) ? 10 : 5); - date.setSeconds(Math.floor(date.getSeconds() / step) * step); - break; - } - - // 1 millisecond - case 1: { - step = (n > 1000) ? 250 : ((n > 200) ? 100 : ((n > 100) ? 50 : ((n > 50) ? 25 : 5))); - date.setMilliseconds(Math.floor(date.getMilliseconds() / step) * step); - break; - } - - // 31536e6 - 1 year - default: { - step = pv.logCeil(n / 15, 10); - if (n / step < 2) step /= 5; - else if (n / step < 5) step /= 2; - date.setFullYear(Math.floor(date.getFullYear() / step) * step); - break; - } - } - } - - - if(dateTickPrecision){ - step = 1; - increment = function(d) { d.setSeconds(d.getSeconds() + step*dateTickPrecision/1000);}; - } - - - while (true) { - increment(date); - if (date > max) break; - dates.push(new Date(date)); - } - return reverse ? dates.reverse() : dates; - } - - /* Normal case: numbers */ - if (m == null) { - m = 10; - } - - var roundInside = pv.get(options, 'roundInside', true); - var exponentMin = pv.get(options, 'numberExponentMin', -Infinity); - var exponentMax = pv.get(options, 'numberExponentMax', +Infinity); - - //var step = pv.logFloor(span / m, 10); - var exponent = Math.floor(pv.log(span / m, 10)); - var overflow = false; - if(exponent > exponentMax){ - exponent = exponentMax; - overflow = true; - } else if(exponent < exponentMin){ - exponent = exponentMin; - overflow = true; - } - - step = Math.pow(10, exponent); - var mObtained = (span / step); - - var err = m / mObtained; - if (err <= .15 && exponent < exponentMax - 1) { - step *= 10; - } else if (err <= .35) { - step *= 5; - } else if (err <= .75) { - step *= 2; - } - - // Account for floating point precision errors - exponent = Math.floor(pv.log(step, 10) + 1e-10); - - start = step * Math[roundInside ? 'ceil' : 'floor'](min / step); - end = step * Math[roundInside ? 'floor' : 'ceil' ](max / step); - - usedNumberExponent = Math.max(0, -exponent); - - tickFormat = pv.Format.number().fractionDigits(usedNumberExponent); - - var ticks = pv.range(start, end + step, step); - if(reverse){ - ticks.reverse(); - } - - ticks.roundInside = roundInside; - ticks.step = step; - ticks.exponent = exponent; - ticks.exponentOverflow = overflow; - ticks.exponentMin = exponentMin; - ticks.exponentMax = exponentMax; - - return ticks; - }; - - - /** - * Formats the specified tick with a well defined string for the date - * @function - * @name pv.Scale.quantitative.prototype.dateTickFormat - * @returns {string} a string with the desired tick format. - */ - scale.dateTickFormat = function () { - if (arguments.length) { - dateTickFormat = arguments[0]; - return this; - } - return dateTickFormat; }; - - /** - * Generates date ticks with a specified precision. - * @function - * @name pv.Scale.quantitative.prototype.dateTickPrecision - * @param {number} [precision] The number of milliseconds that separate ticks. - * @returns {number} the current date tick precision. - */ - scale.dateTickPrecision = function () { - if (arguments.length) { - dateTickPrecision = arguments[0]; - return this; - } - return dateTickPrecision; - }; - - - /** - * Gets or sets a custom tick formatter function. - * - * @function - * @name pv.Scale.quantitative.prototype.tickFormatter - * @param {function} [f] The function that formats number or date ticks. - * When ticks are dates, the second argument of the function is the - * desired tick precision. - * - * @returns {pv.Scale|function} a custom formatter function or this instance. - */ - scale.tickFormatter = function (f) { - if (arguments.length) { - tickFormatter = f; - return this; - } - - return tickFormatter; - }; - - /** - * Formats the specified tick value using the appropriate precision, based on - * the step interval between tick marks. If {@link #ticks} has not been called, - * the argument is converted to a string, but no formatting is applied. - * - * @function - * @name pv.Scale.quantitative.prototype.tickFormat - * @param {number} t a tick value. - * @returns {string} a formatted tick value. - */ - scale.tickFormat = function (t) { - if(tickFormatter){ - return tickFormatter(t, type !== Number ? usedDateTickPrecision : usedNumberExponent); - } - - var formatter = tickFormatter || tickFormat; - return formatter(t); - }; - - /** - * "Nices" this scale, extending the bounds of the input domain to - * evenly-rounded values. Nicing is useful if the domain is computed - * dynamically from data, and may be irregular. For example, given a domain of - * [0.20147987687960267, 0.996679553296417], a call to nice() might - * extend the domain to [0.2, 1]. - * - *

This method must be invoked each time after setting the domain. - * - * @function - * @name pv.Scale.quantitative.prototype.nice - * @returns {pv.Scale.quantitative} this. - */ - scale.nice = function() { - if (d.length != 2) return this; // TODO support non-uniform domains - var start = d[0], - end = d[d.length - 1], - reverse = end < start, - min = reverse ? end : start, - max = reverse ? start : end, - span = max - min; - - /* Special case: empty, invalid or infinite span. */ - if (!span || !isFinite(span)) return this; - - var step = Math.pow(10, Math.round(Math.log(span) / Math.log(10)) - 1); - d = [Math.floor(min / step) * step, Math.ceil(max / step) * step]; - if (reverse) d.reverse(); - l = d.map(f); - return this; - }; - - /** - * Returns a view of this scale by the specified accessor function f. - * Given a scale y, y.by(function(d) d.foo) is equivalent to - * function(d) y(d.foo). - * - *

This method is provided for convenience, such that scales can be - * succinctly defined inline. For example, given an array of data elements - * that have a score attribute with the domain [0, 1], the height - * property could be specified as: - * - *

    .height(pv.Scale.linear().range(0, 480).by(function(d) d.score))
- * - * This is equivalent to: - * - *
    .height(function(d) d.score * 480)
- * - * This method should be used judiciously; it is typically more clear to - * invoke the scale directly, passing in the value to be scaled. - * - * @function - * @name pv.Scale.quantitative.prototype.by - * @param {function} f an accessor function. - * @returns {pv.Scale.quantitative} a view of this scale by the specified - * accessor function. - */ - - pv.copyOwn(scale, pv.Scale.common); - - scale.domain.apply(scale, arguments); - return scale; -}; -/** - * Returns a linear scale for the specified domain. The arguments to this - * constructor are optional, and equivalent to calling {@link #domain}. - * The default domain and range are [0,1]. - * - * @class Represents a linear scale; a function that performs a linear - * transformation. Most - * commonly, a linear scale represents a 1-dimensional linear transformation - * from a numeric domain of input data [d0, - * d1] to a numeric range of pixels [r0, - * r1]. The equation for such a scale is: - * - *
f(x) = (x - d0) / (d1 - d0) * - * (r1 - r0) + r0
- * - * For example, a linear scale from the domain [0, 100] to range [0, 640]: - * - *
f(x) = (x - 0) / (100 - 0) * (640 - 0) + 0
- * f(x) = x / 100 * 640
- * f(x) = x * 6.4
- *
- * - * Thus, saying - * - *
    .height(function(d) d * 6.4)
- * - * is identical to - * - *
    .height(pv.Scale.linear(0, 100).range(0, 640))
- * - * Note that the scale is itself a function, and thus can be used as a property - * directly, assuming that the data associated with a mark is a number. While - * this is convenient for single-use scales, frequently it is desirable to - * define scales globally: - * - *
var y = pv.Scale.linear(0, 100).range(0, 640);
- * - * The y scale can now be equivalently referenced within a property: - * - *
    .height(function(d) y(d))
- * - * Alternatively, if the data are not simple numbers, the appropriate value can - * be passed to the y scale (e.g., d.foo). The {@link #by} - * method similarly allows the data to be mapped to a numeric value before - * performing the linear transformation. - * - * @param {number...} domain... optional domain values. - * @extends pv.Scale.quantitative - */ -pv.Scale.linear = function() { - var scale = pv.Scale.quantitative(); - scale.domain.apply(scale, arguments); - return scale; -}; -/** - * Returns a log scale for the specified domain. The arguments to this - * constructor are optional, and equivalent to calling {@link #domain}. - * The default domain is [1,10] and the default range is [0,1]. - * - * @class Represents a log scale. Most commonly, a log scale - * represents a 1-dimensional log transformation from a numeric domain of input - * data [d0, d1] to a numeric range of - * pixels [r0, r1]. The equation for such a - * scale is: - * - *
f(x) = (log(x) - log(d0)) / (log(d1) - - * log(d0)) * (r1 - r0) + - * r0
- * - * where log(x) represents the zero-symmetric logarthim of x using - * the scale's associated base (default: 10, see {@link pv.logSymmetric}). For - * example, a log scale from the domain [1, 100] to range [0, 640]: - * - *
f(x) = (log(x) - log(1)) / (log(100) - log(1)) * (640 - 0) + 0
- * f(x) = log(x) / 2 * 640
- * f(x) = log(x) * 320
- *
- * - * Thus, saying - * - *
    .height(function(d) Math.log(d) * 138.974)
- * - * is equivalent to - * - *
    .height(pv.Scale.log(1, 100).range(0, 640))
- * - * Note that the scale is itself a function, and thus can be used as a property - * directly, assuming that the data associated with a mark is a number. While - * this is convenient for single-use scales, frequently it is desirable to - * define scales globally: - * - *
var y = pv.Scale.log(1, 100).range(0, 640);
- * - * The y scale can now be equivalently referenced within a property: - * - *
    .height(function(d) y(d))
- * - * Alternatively, if the data are not simple numbers, the appropriate value can - * be passed to the y scale (e.g., d.foo). The {@link #by} - * method similarly allows the data to be mapped to a numeric value before - * performing the log transformation. - * - * @param {number...} domain... optional domain values. - * @extends pv.Scale.quantitative - */ -pv.Scale.log = function() { - var scale = pv.Scale.quantitative(1, 10), - b, // logarithm base - p, // cached Math.log(b) - /** @ignore */ log = function(x) { return Math.log(x) / p; }, - /** @ignore */ pow = function(y) { return Math.pow(b, y); }; - - /** - * Returns an array of evenly-spaced, suitably-rounded values in the input - * domain. These values are frequently used in conjunction with - * {@link pv.Rule} to display tick marks or grid lines. - * - * @function - * @name pv.Scale.log.prototype.ticks - * @returns {number[]} an array input domain values to use as ticks. - */ - scale.ticks = function() { - // TODO support non-uniform domains - var d = scale.domain(), - n = d[0] < 0, - i = Math.floor(n ? -log(-d[0]) : log(d[0])), - j = Math.ceil(n ? -log(-d[1]) : log(d[1])), - ticks = []; - if (n) { - ticks.push(-pow(-i)); - for (; i++ < j;) for (var k = b - 1; k > 0; k--) ticks.push(-pow(-i) * k); - } else { - for (; i < j; i++) for (var k = 1; k < b; k++) ticks.push(pow(i) * k); - ticks.push(pow(i)); - } - for (i = 0; ticks[i] < d[0]; i++); // strip small values - for (j = ticks.length; ticks[j - 1] > d[1]; j--); // strip big values - return ticks.slice(i, j); - }; - - /** - * Formats the specified tick value using the appropriate precision, assuming - * base 10. - * - * @function - * @name pv.Scale.log.prototype.tickFormat - * @param {number} t a tick value. - * @returns {string} a formatted tick value. - */ - scale.tickFormat = function(t) { - return t.toPrecision(1); - }; - - /** - * "Nices" this scale, extending the bounds of the input domain to - * evenly-rounded values. This method uses {@link pv.logFloor} and - * {@link pv.logCeil}. Nicing is useful if the domain is computed dynamically - * from data, and may be irregular. For example, given a domain of - * [0.20147987687960267, 0.996679553296417], a call to nice() might - * extend the domain to [0.1, 1]. - * - *

This method must be invoked each time after setting the domain (and - * base). - * - * @function - * @name pv.Scale.log.prototype.nice - * @returns {pv.Scale.log} this. - */ - scale.nice = function() { - // TODO support non-uniform domains - var d = scale.domain(); - return scale.domain(pv.logFloor(d[0], b), pv.logCeil(d[1], b)); - }; - - /** - * Sets or gets the logarithm base. Defaults to 10. - * - * @function - * @name pv.Scale.log.prototype.base - * @param {number} [v] the new base. - * @returns {pv.Scale.log} this, or the current base. - */ - scale.base = function(v) { - if (arguments.length) { - b = Number(v); - p = Math.log(b); - scale.transform(log, pow); // update transformed domain - return this; - } - return b; - }; - - scale.domain.apply(scale, arguments); - return scale.base(10); -}; -/** - * Returns a root scale for the specified domain. The arguments to this - * constructor are optional, and equivalent to calling {@link #domain}. - * The default domain and range are [0,1]. - * - * @class Represents a root scale; a function that performs a power - * transformation. Most - * commonly, a root scale represents a 1-dimensional root transformation from a - * numeric domain of input data [d0, d1] to - * a numeric range of pixels [r0, r1]. - * - *

Note that the scale is itself a function, and thus can be used as a - * property directly, assuming that the data associated with a mark is a - * number. While this is convenient for single-use scales, frequently it is - * desirable to define scales globally: - * - *

var y = pv.Scale.root(0, 100).range(0, 640);
- * - * The y scale can now be equivalently referenced within a property: - * - *
    .height(function(d) y(d))
- * - * Alternatively, if the data are not simple numbers, the appropriate value can - * be passed to the y scale (e.g., d.foo). The {@link #by} - * method similarly allows the data to be mapped to a numeric value before - * performing the root transformation. - * - * @param {number...} domain... optional domain values. - * @extends pv.Scale.quantitative - */ -pv.Scale.root = function() { - var scale = pv.Scale.quantitative(); - - /** - * Sets or gets the exponent; defaults to 2. - * - * @function - * @name pv.Scale.root.prototype.power - * @param {number} [v] the new exponent. - * @returns {pv.Scale.root} this, or the current base. - */ - scale.power = function(v) { - if (arguments.length) { - var b = Number(v), p = 1 / b; - scale.transform( - function(x) { return Math.pow(x, p); }, - function(y) { return Math.pow(y, b); }); - return this; - } - return b; - }; - - scale.domain.apply(scale, arguments); - return scale.power(2); -}; -/** - * Returns an ordinal scale for the specified domain. The arguments to this - * constructor are optional, and equivalent to calling {@link #domain}. - * - * @class Represents an ordinal scale. An ordinal scale represents a - * pairwise mapping from n discrete values in the input domain to - * n discrete values in the output range. For example, an ordinal scale - * might map a domain of species ["setosa", "versicolor", "virginica"] to colors - * ["red", "green", "blue"]. Thus, saying - * - *
    .fillStyle(function(d) {
- *         switch (d.species) {
- *           case "setosa": return "red";
- *           case "versicolor": return "green";
- *           case "virginica": return "blue";
- *         }
- *       })
- * - * is equivalent to - * - *
    .fillStyle(pv.Scale.ordinal("setosa", "versicolor", "virginica")
- *         .range("red", "green", "blue")
- *         .by(function(d) d.species))
- * - * If the mapping from species to color does not need to be specified - * explicitly, the domain can be omitted. In this case it will be inferred - * lazily from the data: - * - *
    .fillStyle(pv.colors("red", "green", "blue")
- *         .by(function(d) d.species))
- * - * When the domain is inferred, the first time the scale is invoked, the first - * element from the range will be returned. Subsequent calls with unique values - * will return subsequent elements from the range. If the inferred domain grows - * larger than the range, range values will be reused. However, it is strongly - * recommended that the domain and the range contain the same number of - * elements. - * - *

A range can be discretized from a continuous interval (e.g., for pixel - * positioning) by using {@link #split}, {@link #splitFlush} or - * {@link #splitBanded} after the domain has been set. For example, if - * states is an array of the fifty U.S. state names, the state name can - * be encoded in the left position: - * - *

    .left(pv.Scale.ordinal(states)
- *         .split(0, 640)
- *         .by(function(d) d.state))
- * - *

N.B.: ordinal scales are not invertible (at least not yet), since the - * domain and range and discontinuous. A workaround is to use a linear scale. - * - * @param {...} domain... optional domain values. - * @extends pv.Scale - * @see pv.colors - */ -pv.Scale.ordinal = function() { - var d = [], i = {}, r = [], band = 0; - - /** @private */ - function scale(x) { - if (!(x in i)) i[x] = d.push(x) - 1; - return r[i[x] % r.length]; - } - - /** - * Sets or gets the input domain. This method can be invoked several ways: - * - *

1. domain(values...) - * - *

Specifying the domain as a series of values is the most explicit and - * recommended approach. However, if the domain values are derived from data, - * you may find the second method more appropriate. - * - *

2. domain(array, f) - * - *

Rather than enumerating the domain values as explicit arguments to this - * method, you can specify a single argument of an array. In addition, you can - * specify an optional accessor function to extract the domain values from the - * array. - * - *

3. domain() - * - *

Invoking the domain method with no arguments returns the - * current domain as an array. - * - * @function - * @name pv.Scale.ordinal.prototype.domain - * @param {...} domain... domain values. - * @returns {pv.Scale.ordinal} this, or the current domain. - */ - scale.domain = function(array, f) { - if (arguments.length) { - array = (array instanceof Array) - ? ((arguments.length > 1) ? pv.map(array, f) : array) - : Array.prototype.slice.call(arguments); - - /* Filter the specified ordinals to their unique values. */ - d = []; - var seen = {}; - for (var j = 0; j < array.length; j++) { - var o = array[j]; - if (!(o in seen)) { - seen[o] = true; - d.push(o); - } - } - - i = pv.numerate(d); - return this; - } - return d; - }; - - /** - * Sets or gets the output range. This method can be invoked several ways: - * - *

1. range(values...) - * - *

Specifying the range as a series of values is the most explicit and - * recommended approach. However, if the range values are derived from data, - * you may find the second method more appropriate. - * - *

2. range(array, f) - * - *

Rather than enumerating the range values as explicit arguments to this - * method, you can specify a single argument of an array. In addition, you can - * specify an optional accessor function to extract the range values from the - * array. - * - *

3. range() - * - *

Invoking the range method with no arguments returns the - * current range as an array. - * - * @function - * @name pv.Scale.ordinal.prototype.range - * @param {...} range... range values. - * @returns {pv.Scale.ordinal} this, or the current range. - */ - scale.range = function(array, f) { - if (arguments.length) { - r = (array instanceof Array) - ? ((arguments.length > 1) ? pv.map(array, f) : array) - : Array.prototype.slice.call(arguments); - if (typeof r[0] == "string") r = r.map(pv.color); - r.min = r[0]; - r.max = r[r.length - 1]; - return this; - } - return r; - }; - - /** - * Sets the range from the given continuous interval. The interval - * [min, max] is subdivided into n equispaced points, - * where n is the number of (unique) values in the domain. The first - * and last point are offset from the edge of the range by half the distance - * between points. - * - *

This method must be called after the domain is set. - *

- * The computed step width can be retrieved from the range as - * scale.range().step. - *

- * - * @function - * @name pv.Scale.ordinal.prototype.split - * @param {number} min minimum value of the output range. - * @param {number} max maximum value of the output range. - * @returns {pv.Scale.ordinal} this. - * @see #splitFlush - * @see #splitBanded - */ - scale.split = function(min, max) { - var R = max - min; - var N = this.domain().length; - var step = 0; - if(R === 0){ - r = pv.array(N, min); - } else if(N){ - step = (max - min) / N; - r = pv.range(min + step / 2, max, step); - } - r.min = min; - r.max = max; - r.step = step; - return this; - }; - - /** - * Sets the range from the given continuous interval. - * The interval [min, max] is subdivided into n equispaced bands, - * where n is the number of (unique) values in the domain. - * - * The first and last band are offset from the edge of the range by - * half the distance between bands. - * - * The positions are centered in each band. - *
-	 * m = M/2
-	 *
-	 *  |mBm|mBm| ... |mBm|
-	 * min               max
-	 *   r0 -> min + m + B/2
-	 * 
- *

This method must be called after the domain is set.

- *

- * The computed absolute band width can be retrieved from the range as - * scale.range().band. - * The properties step and margin are also exposed. - *

- * - * @function - * @name pv.Scale.ordinal.prototype.splitBandedCenter - * @param {number} min minimum value of the output range. - * @param {number} max maximum value of the output range. - * @param {number} [band] the fractional band width in [0, 1]; defaults to 1. - * @returns {pv.Scale.ordinal} this. - * @see #split - */ - scale.splitBandedCenter = function(min, max, band) { - scale.split(min, max); - if (band == null) { - band = 1; - } - r.band = r.step * band; - r.margin = r.step - r.band; - r.min = min; - r.max = max; - return this; - }; - - /** - * Sets the range from the given continuous interval. - * The interval [min, max] is subdivided into n equispaced bands, - * where n is the number of (unique) values in the domain. - * - * The first and last bands are aligned to the edges of the range. - *
-	 *  |Bm|mBm| ...|mB|
-	 *  or
-	 *  |BM |BM |... |B|
-	 * min           max
-	 *   r0 -> min + B/2
-	 * 
- *

- * The positions are centered in each band - * (the first position is at min + band / 2). - *

- *

This method must be called after the domain is set.

- *

- * The computed absolute band width can be retrieved from the range as - * scale.range().band. - * The properties step and margin are also exposed. - *

- * - * @function - * @name pv.Scale.ordinal.prototype.splitBandedFlushCenter - * @param {number} min minimum value of the output range. - * @param {number} max maximum value of the output range. - * @param {number} [band] the fractional band width in [0, 1]; defaults to 1. - * @returns {pv.Scale.ordinal} this. - * @see #split - */ - scale.splitBandedFlushCenter = function(min, max, band) { - if (band == null) { - band = 1; - } - - var R = (max - min), - N = this.domain().length, - S = 0, - B = 0, - M = 0; - if(R === 0){ - r = pv.array(N, min); - } else if(N){ - B = (R * band) / N; - M = N > 1 ? ((R - N * B) / (N - 1)) : 0; - S = M + B; - - r = pv.range(min + B / 2, max, S); - } - - r.step = S; - r.band = B; - r.margin = M; - r.min = min; - r.max = max; - return this; - }; - - /** - * Sets the range from the given continuous interval. The interval - * [min, max] is subdivided into n equispaced points, - * where n is the number of (unique) values in the domain. The first - * and last point are exactly on the edge of the range. - * - *

This method must be called after the domain is set. - * - * @function - * @name pv.Scale.ordinal.prototype.splitFlush - * @param {number} min minimum value of the output range. - * @param {number} max maximum value of the output range. - * @returns {pv.Scale.ordinal} this. - * @see #split - */ - scale.splitFlush = function(min, max) { - var n = this.domain().length, - step = (max - min) / (n - 1); - - r = (n == 1) ? [(min + max) / 2] - : pv.range(min, max + step / 2, step); - r.min = min; - r.max = max; - return this; - }; - - /** - * Sets the range from the given continuous interval. The interval - * [min, max] is subdivided into n equispaced bands, - * where n is the number of (unique) values in the domain. The first - * and last band are offset from the edge of the range by the distance between - * bands. - * - *

The band width argument, band, is typically in the range [0, 1] - * and defaults to 1. This fraction corresponds to the amount of space in the - * range to allocate to the bands, as opposed to padding. A value of 0.5 means - * that the band width will be equal to the padding width. The computed - * absolute band width can be retrieved from the range as - * scale.range().band. - * The properties step and margin are also exposed. - *

- * - *
-	 * m = M/2
-	 *
-	 *  |MBm|mBm| ... |mBM|
-	 * min               max
-	 *   r0 -> min + M
-	 * 
- * - *

If the band width argument is negative, this method will allocate bands - * of a fixed width -band, rather than a relative fraction of - * the available space. - * - *

Tip: to inset the bands by a fixed amount p, specify a minimum - * value of min + p (or simply p, if min is - * 0). Then set the mark width to scale.range().band - p. - * - *

This method must be called after the domain is set. - * - * @function - * @name pv.Scale.ordinal.prototype.splitBanded - * @param {number} min minimum value of the output range. - * @param {number} max maximum value of the output range. - * @param {number} [band] the fractional band width in [0, 1]; defaults to 1. - * @returns {pv.Scale.ordinal} this. - * @see #split - */ - scale.splitBanded = function(min, max, band) { - if (arguments.length < 3) band = 1; - if (band < 0) { - var n = this.domain().length, - total = -band * n, - remaining = max - min - total, - padding = remaining / (n + 1); - r = pv.range(min + padding, max, padding - band); - r.band = -band; - } else { - var step = (max - min) / (this.domain().length + (1 - band)); - r = pv.range(min + step * (1 - band), max, step); - r.band = step * band; - r.step = step; - r.margin = step - r.band; - } - r.min = min; - r.max = max; - return this; - }; - - /** - * Inverts the specified value in the output range, - * returning the index of the closest corresponding value in the input domain. - * This is frequently used to convert the mouse location (see {@link pv.Mark#mouse}) - * to a value in the input domain. - * - * The number of input domain values is returned - * if the specified point is closest to the end margin of the last input domain value. - * - * @function - * @name pv.Scale.quantitative.prototype.invertIndex - * @param {number} y a value in the output range (a pixel location). - * @param {boolean} [noRound=false] returns an un-rounded result. - * @returns {number} the index of the closest input domain value. - */ - scale.invertIndex = function(y, noRound) { - var N = this.domain().length; - if(N === 0){ - return -1; - } - - var r = this.range(); - var R = r.max - r.min; - if(R === 0){ - return 0; - } - - var S = R/N; - if(y >= r.max){ - return N; - } - - if(y < r.min){ - return 0; - } - - var i = (y - r.min) / S; - return noRound ? i : Math.round(i); - }; - - /** - * Returns a view of this scale by the specified accessor function f. - * Given a scale y, y.by(function(d) d.foo) is equivalent to - * function(d) y(d.foo). This method should be used judiciously; it - * is typically more clear to invoke the scale directly, passing in the value - * to be scaled. - * - * @function - * @name pv.Scale.ordinal.prototype.by - * @param {function} f an accessor function. - * @returns {pv.Scale.ordinal} a view of this scale by the specified accessor - * function. - */ - - pv.copyOwn(scale, pv.Scale.common); - - scale.domain.apply(scale, arguments); - return scale; -}; -/** - * Constructs a default quantile scale. The arguments to this constructor are - * optional, and equivalent to calling {@link #domain}. The default domain is - * the empty set, and the default range is [0,1]. - * - * @class Represents a quantile scale; a function that maps from a value within - * a sortable domain to a quantized numeric range. Typically, the domain is a - * set of numbers, but any sortable value (such as strings) can be used as the - * domain of a quantile scale. The range defaults to [0,1], with 0 corresponding - * to the smallest value in the domain, 1 the largest, .5 the median, etc. - * - *

By default, the number of quantiles in the range corresponds to the number - * of values in the domain. The {@link #quantiles} method can be used to specify - * an explicit number of quantiles; for example, quantiles(4) produces - * a standard quartile scale. A quartile scale's range is a set of four discrete - * values, such as [0, 1/3, 2/3, 1]. Calling the {@link #range} method will - * scale these discrete values accordingly, similar to {@link - * pv.Scale.ordinal#splitFlush}. - * - *

For example, given the strings ["c", "a", "b"], a default quantile scale: - * - *

pv.Scale.quantile("c", "a", "b")
- * - * will return 0 for "a", .5 for "b", and 1 for "c". - * - * @extends pv.Scale - */ -pv.Scale.quantile = function() { - var n = -1, // number of quantiles - j = -1, // max quantile index - q = [], // quantile boundaries - d = [], // domain - y = pv.Scale.linear(); // range - - /** @private */ - function scale(x) { - return y(Math.max(0, Math.min(j, pv.search.index(q, x) - 1)) / j); - } - - /** - * Sets or gets the quantile boundaries. By default, each element in the - * domain is in its own quantile. If the argument to this method is a number, - * it specifies the number of equal-sized quantiles by which to divide the - * domain. - * - *

If no arguments are specified, this method returns the quantile - * boundaries; the first element is always the minimum value of the domain, - * and the last element is the maximum value of the domain. Thus, the length - * of the returned array is always one greater than the number of quantiles. - * - * @function - * @name pv.Scale.quantile.prototype.quantiles - * @param {number} x the number of quantiles. - */ - scale.quantiles = function(x) { - if (arguments.length) { - n = Number(x); - if (n < 0) { - q = [d[0]].concat(d); - j = d.length - 1; - } else { - q = []; - q[0] = d[0]; - for (var i = 1; i <= n; i++) { - q[i] = d[~~(i * (d.length - 1) / n)]; - } - j = n - 1; - } - return this; - } - return q; - }; - - /** - * Sets or gets the input domain. This method can be invoked several ways: - * - *

1. domain(values...) - * - *

Specifying the domain as a series of values is the most explicit and - * recommended approach. However, if the domain values are derived from data, - * you may find the second method more appropriate. - * - *

2. domain(array, f) - * - *

Rather than enumerating the domain values as explicit arguments to this - * method, you can specify a single argument of an array. In addition, you can - * specify an optional accessor function to extract the domain values from the - * array. - * - *

3. domain() - * - *

Invoking the domain method with no arguments returns the - * current domain as an array. - * - * @function - * @name pv.Scale.quantile.prototype.domain - * @param {...} domain... domain values. - * @returns {pv.Scale.quantile} this, or the current domain. - */ - scale.domain = function(array, f) { - if (arguments.length) { - d = (array instanceof Array) - ? pv.map(array, f) - : Array.prototype.slice.call(arguments); - d.sort(pv.naturalOrder); - scale.quantiles(n); // recompute quantiles - return this; - } - return d; - }; - - /** - * Sets or gets the output range. This method can be invoked several ways: - * - *

1. range(min, ..., max) - * - *

The range may be specified as a series of numbers or colors. Most - * commonly, two numbers are specified: the minimum and maximum pixel values. - * For a color scale, values may be specified as {@link pv.Color}s or - * equivalent strings. For a diverging scale, or other subdivided non-uniform - * scales, multiple values can be specified. For example: - * - *

    .range("red", "white", "green")
- * - *

Currently, only numbers and colors are supported as range values. The - * number of range values must exactly match the number of domain values, or - * the behavior of the scale is undefined. - * - *

2. range() - * - *

Invoking the range method with no arguments returns the current - * range as an array of numbers or colors. - * - * @function - * @name pv.Scale.quantile.prototype.range - * @param {...} range... range values. - * @returns {pv.Scale.quantile} this, or the current range. - */ - scale.range = function() { - if (arguments.length) { - y.range.apply(y, arguments); - return this; - } - return y.range(); - }; - - /** - * Returns a view of this scale by the specified accessor function f. - * Given a scale y, y.by(function(d) d.foo) is equivalent to - * function(d) y(d.foo). - * - *

This method is provided for convenience, such that scales can be - * succinctly defined inline. For example, given an array of data elements - * that have a score attribute with the domain [0, 1], the height - * property could be specified as: - * - *

.height(pv.Scale.linear().range(0, 480).by(function(d) d.score))
- * - * This is equivalent to: - * - *
.height(function(d) d.score * 480)
- * - * This method should be used judiciously; it is typically more clear to - * invoke the scale directly, passing in the value to be scaled. - * - * @function - * @name pv.Scale.quantile.prototype.by - * @param {function} f an accessor function. - * @returns {pv.Scale.quantile} a view of this scale by the specified - * accessor function. - */ - - pv.copyOwn(scale, pv.Scale.common); - - scale.domain.apply(scale, arguments); - return scale; -}; -/** - * Returns a histogram operator for the specified data, with an optional - * accessor function. If the data specified is not an array of numbers, an - * accessor function must be specified to map the data to numeric values. - * - * @class Represents a histogram operator. - * - * @param {array} data an array of numbers or objects. - * @param {function} [f] an optional accessor function. - */ -pv.histogram = function(data, f) { - var frequency = true; - return { - - /** - * Returns the computed histogram bins. An optional array of numbers, - * ticks, may be specified as the break points. If the ticks are - * not specified, default ticks will be computed using a linear scale on the - * data domain. - * - *

The returned array contains {@link pv.histogram.Bin}s. The x - * attribute corresponds to the bin's start value (inclusive), while the - * dx attribute stores the bin size (end - start). The y - * attribute stores either the frequency count or probability, depending on - * how the histogram operator has been configured. - * - *

The {@link pv.histogram.Bin} objects are themselves arrays, containing - * the data elements present in each bin, i.e., the elements in the - * data array (prior to invoking the accessor function, if any). - * For example, if the data represented countries, and the accessor function - * returned the GDP of each country, the returned bins would be arrays of - * countries (not GDPs). - * - * @function - * @name pv.histogram.prototype.bins - * @param {array} [ticks] - * @returns {array} - */ /** @private */ - bins: function(ticks) { - var x = pv.map(data, f), bins = []; - - /* Initialize default ticks. */ - if (!arguments.length) ticks = pv.Scale.linear(x).ticks(); - - /* Initialize the bins. */ - for (var i = 0; i < ticks.length - 1; i++) { - var bin = bins[i] = []; - bin.x = ticks[i]; - bin.dx = ticks[i + 1] - ticks[i]; - bin.y = 0; - } - - /* Count the number of samples per bin. */ - for (var i = 0; i < x.length; i++) { - var j = pv.search.index(ticks, x[i]) - 1, - bin = bins[Math.max(0, Math.min(bins.length - 1, j))]; - bin.y++; - bin.push(data[i]); - } - - /* Convert frequencies to probabilities. */ - if (!frequency) for (var i = 0; i < bins.length; i++) { - bins[i].y /= x.length; - } - - return bins; - }, - - /** - * Sets or gets whether this histogram operator returns frequencies or - * probabilities. - * - * @function - * @name pv.histogram.prototype.frequency - * @param {boolean} [x] - * @returns {pv.histogram} this. - */ /** @private */ - frequency: function(x) { - if (arguments.length) { - frequency = Boolean(x); - return this; - } - return frequency; - } - }; -}; - -/** - * @class Represents a bin returned by the {@link pv.histogram} operator. Bins - * are themselves arrays containing the data elements present in the given bin - * (prior to the accessor function being invoked to convert the data object to a - * numeric value). These bin arrays have additional attributes with meta - * information about the bin. - * - * @name pv.histogram.Bin - * @extends array - * @see pv.histogram - */ - -/** - * The start value of the bin's range. - * - * @type number - * @name pv.histogram.Bin.prototype.x - */ - -/** - * The magnitude value of the bin's range; end - start. - * - * @type number - * @name pv.histogram.Bin.prototype.dx - */ - -/** - * The frequency or probability of the bin, depending on how the histogram - * operator was configured. - * - * @type number - * @name pv.histogram.Bin.prototype.y - */ - -(function(){ - - pv.Shape = function(){}; - - // ----------------- - - var _k0 = {x: 1, y: 1}; - - pv.Shape.dist2 = function(v, w, k) { - k = k || _k0; - - var dx = v.x - w.x; - var dy = v.y - w.y; - var dx2 = dx*dx; - var dy2 = dy*dy; - - return { - cost: dx2 + dy2, - dist2: k.x * dx2 + k.y * dy2 - }; - }; - - // Returns an angle between 0 and and 2*pi - var pi = Math.PI; - var pi2 = 2 * pi; - var atan2 = Math.atan2; - - pv.Shape.normalizeAngle = function(a){ - a = a % pi2; - if(a < 0){ - a += pi2; - } - - return a; - }; - - // 0 - 2*pi - pv.Shape.atan2Norm = function(dy, dx){ - // between -pi and pi - var a = atan2(dy, dx); - if(a < 0){ - a += pi2; - } - - return a; - }; - - // ----------------- - - pv.Shape.prototype.hasArea = function(){ - return true; - }; - - // hasArea - // apply - // clone - // intersectsRect - // intersectLine (some) - // containsPoint - // points - // edges - // center - // distance2 - // bbox (some) - -}()); -(function(){ - - var dist2 = pv.Shape.dist2; - var cos = Math.cos; - var sin = Math.sin; - var sqrt = Math.sqrt; - - - /** - * Returns a {@link pv.Vector} for the specified x and y - * coordinate. This is a convenience factory method, equivalent to new - * pv.Vector(x, y). - * - * @see pv.Vector - * @param {number} x the x coordinate. - * @param {number} y the y coordinate. - * @returns {pv.Vector} a vector for the specified coordinates. - */ - pv.vector = function(x, y) { - return new Point(x, y); - }; - - /** - * Constructs a {@link pv.Vector} for the specified x and y - * coordinate. This constructor should not be invoked directly; use - * {@link pv.vector} instead. - * - * @class Represents a two-dimensional vector; a 2-tuple ⟨x, - * y⟩. The intent of this class is to simplify vector math. Note that - * in performance-sensitive cases it may be more efficient to represent 2D - * vectors as simple objects with x and y attributes, rather - * than using instances of this class. - * - * @param {number} x the x coordinate. - * @param {number} y the y coordinate. - */ - pv.Vector = function(x, y) { - this.x = x; - this.y = y; - }; - - var Point = pv.Shape.Point = pv.Vector; - - pv.Vector.prototype = pv.extend(pv.Shape); - - /** - * Returns a vector perpendicular to this vector: ⟨-y, x⟩. - * - * @returns {pv.Vector} a perpendicular vector. - */ - pv.Vector.prototype.perp = function() { - return new Point(-this.y, this.x); - }; - - /** - * Returns a vector which is the result of rotating this vector by the specified angle. - * - * @returns {pv.Vector} a rotated vector. - */ - pv.Vector.prototype.rotate = function(angle) { - var c = cos(angle); - var s = sin(angle); - - return new Point(c*this.x -s*this.y, s*this.x + c*this.y); - }; - - /** - * Returns a normalized copy of this vector: a vector with the same direction, - * but unit length. If this vector has zero length this method returns a copy of - * this vector. - * - * @returns {pv.Vector} a unit vector. - */ - pv.Vector.prototype.norm = function() { - var l = this.length(); - return this.times(l ? (1 / l) : 1); - }; - - /** - * Returns the magnitude of this vector, defined as sqrt(x * x + y * y). - * - * @returns {number} a length. - */ - pv.Vector.prototype.length = function() { - return sqrt(this.x * this.x + this.y * this.y); - }; - - /** - * Returns a scaled copy of this vector: ⟨x * k, y * k⟩. - * To perform the equivalent divide operation, use 1 / k. - * - * @param {number} k the scale factor. - * @returns {pv.Vector} a scaled vector. - */ - pv.Vector.prototype.times = function(k) { - return new Point(this.x * k, this.y * k); - }; - - /** - * Returns this vector plus the vector v: ⟨x + v.x, y + - * v.y⟩. If only one argument is specified, it is interpreted as the - * vector v. - * - * @param {number} x the x coordinate to add. - * @param {number} y the y coordinate to add. - * @returns {pv.Vector} a new vector. - */ - pv.Vector.prototype.plus = function(x, y) { - return (arguments.length == 1) - ? new Point(this.x + x.x, this.y + x.y) - : new Point(this.x + x, this.y + y); - }; - - /** - * Returns this vector minus the vector v: ⟨x - v.x, y - - * v.y⟩. If only one argument is specified, it is interpreted as the - * vector v. - * - * @param {number} x the x coordinate to subtract. - * @param {number} y the y coordinate to subtract. - * @returns {pv.Vector} a new vector. - */ - pv.Vector.prototype.minus = function(x, y) { - return (arguments.length == 1) - ? new Point(this.x - x.x, this.y - x.y) - : new Point(this.x - x, this.y - y); - }; - - /** - * Returns the dot product of this vector and the vector v: x * v.x + - * y * v.y. If only one argument is specified, it is interpreted as the - * vector v. - * - * @param {number} x the x coordinate to dot. - * @param {number} y the y coordinate to dot. - * @returns {number} a dot product. - */ - pv.Vector.prototype.dot = function(x, y) { - return (arguments.length == 1) - ? this.x * x.x + this.y * x.y - : this.x * x + this.y * y; - }; - - pv.Vector.prototype.hasArea = function(){ - return false; - }; - - pv.Vector.prototype.clone = function(){ - return new Point(this.x, this.y); - }; - - pv.Vector.prototype.apply = function(t){ - return new Point(t.x + (t.k * this.x), t.y + (t.k * this.y)); - }; - - pv.Vector.prototype.intersectsRect = function(rect){ - // Does rect contain the point - return (this.x >= rect.x) && (this.x <= rect.x2) && - (this.y >= rect.y) && (this.y <= rect.y2); - }; - - pv.Vector.prototype.containsPoint = function(p){ - return (this.x === p.x) && (this.y === p.y); - }; - - pv.Vector.prototype.points = function(){ - return [this]; - }; - - pv.Vector.prototype.edges = function(){ - return []; - }; - - pv.Vector.prototype.center = function(){ - return this; - }; - - pv.Vector.prototype.distance2 = function(p, k){ - return dist2(this, p, k); - }; -}()); - -(function(){ - var Point = pv.Shape.Point; - var dist2 = pv.Shape.dist2; - - // ----------------- - - pv.Shape.Line = function(x, y, x2, y2){ - this.x = x || 0; - this.y = y || 0; - this.x2 = x2 || 0; - this.y2 = y2 || 0; - }; - - var Line = pv.Shape.Line; - - Line.prototype = pv.extend(pv.Shape); - - Line.prototype.hasArea = function(){ - return false; - }; - - Line.prototype.clone = function(){ - return new Line(this.x, this.y, this.x2, this.x2); - }; - - Line.prototype.apply = function(t){ - var x = t.x + (t.k * this.x ); - var y = t.y + (t.k * this.y ); - var x2 = t.x + (t.k * this.x2); - var y2 = t.y + (t.k * this.y2); - return new Line(x, y, x2, y2); - }; - - Line.prototype.points = function(){ - return [new Point(this.x, this.y), new Point(this.x2, this.y2)]; - }; - - Line.prototype.edges = function(){ - return [this]; - }; - - Line.prototype.center = function(){ - return new Point((this.x + this.x2)/2, (this.y + this.y2)/2); - }; - - Line.prototype.normal = function(at, shapeCenter){ - // Any point (at) laying on the line has the same normal - var points = this.points(); - var norm = points[1].minus(points[0]).perp().norm(); - - // If shapeCenter point is specified, - // return the norm direction that - // points to the outside of the shape - if(shapeCenter){ - var outside = points[0].minus(shapeCenter); - if(outside.dot(norm) < 0){ - // opposite directions - norm = norm.times(-1); - } - } - - return norm; - }; - - Line.prototype.intersectsRect = function(rect){ - var i, L; - var points = this.points(); - L = points.length; - for(i = 0 ; i < L ; i++){ - if(points[i].intersectsRect(rect)){ - return true; - } - } - - var edges = rect.edges(); - L = edges.length; - for(i = 0 ; i < L ; i++){ - if(this.intersectsLine(edges[i])){ - return true; - } - } - - return false; - }; - - Line.prototype.containsPoint = function(p){ - var x = this.x ; - var x2 = this.x2; - var y = this.y ; - var y2 = this.y2; - return x <= p.x && p.x <= x2 && - ((x === x2) ? - (Math.min(y, y2) <= p.y && p.y <= Math.max(y, y2)) : - (Math.abs((y2-y)/(x2-x) * (p.x-x) + y - p.y) <= 1e-10)); - }; - - Line.prototype.intersectsLine = function(b){ - // See: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ - var a = this, - - x21 = a.x2 - a.x, - y21 = a.y2 - a.y, - - x43 = b.x2 - b.x, - y43 = b.y2 - b.y, - - denom = y43 * x21 - x43 * y21; - - if(denom === 0){ - // Parallel lines: no intersection - return false; - } - - var y13 = a.y - b.y, - x13 = a.x - b.x, - numa = (x43 * y13 - y43 * x13), - numb = (x21 * y13 - y21 * x13); - - if(denom === 0){ - // Both 0 => coincident - // Only denom 0 => parallel, but not coincident - return (numa === 0) && (numb === 0); - } - - var ua = numa / denom; - if(ua < 0 || ua > 1){ - // Intersection not within segment a - return false; - } - - var ub = numb / denom; - if(ub < 0 || ub > 1){ - // Intersection not within segment b - return false; - } - - return true; - }; - - // Adapted from http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment (commenter Grumdrig) - // Return minimum distance (squared) between the point p and the line segment - // k: cost vector - Line.prototype.distance2 = function(p, k){ - var v = this; - var w = {x: this.x2, y: this.y2}; - - var l2 = dist2(v, w).dist2; - if (l2 <= 1e-10) { - // v == w case - return dist2(p, v, k); - } - - // Consider the line extending the segment, parameterized as v + t (w - v). - // We find projection of point p onto the line. - // It falls where t = [(p-v) . (w-v)] / |w-v|^2 - var wvx = w.x - v.x; - var wvy = w.y - v.y; - - var t = ((p.x - v.x) * wvx + (p.y - v.y) * wvy) / l2; - - if (t < 0) { return dist2(p, v, k); } // lies before v, so return the distance between v and p - - if (t > 1) { return dist2(p, w, k); } // lies after w, so return the distance between w and p - - var proj = {x: v.x + t * wvx, y: v.y + t * wvy}; - - return dist2(p, proj, k); - }; - -}()); - -(function(){ - - var Point = pv.Shape.Point; - var Line = pv.Shape.Line; - - pv.Shape.Polygon = function(points){ - this._points = points || []; - }; - - var Polygon = pv.Shape.Polygon; - - Polygon.prototype = pv.extend(pv.Shape); - - Polygon.prototype.points = function(){ - return this._points; - }; - - Polygon.prototype.clone = function(){ - return new Polygon(this.points().slice()); - }; - - Polygon.prototype.apply = function(t){ - var points = this.points(); - var L = points.length; - var points2 = new Array(L); - - for(var i = 0 ; i < L ; i++){ - points2[i] = points[i].apply(t); - } - - return new Polygon(points2); - }; - - Polygon.prototype.intersectsRect = function(rect){ - // I - Any point is inside the rect? - var i, L; - var points = this.points(); - - L = points.length; - for(i = 0 ; i < L ; i++){ - if(points[i].intersectsRect(rect)){ - return true; - } - } - - // II - Any side intersects the rect? - var edges = this.edges(); - L = edges.length; - for(i = 0 ; i < L ; i++){ - if(edges[i].intersectsRect(rect)){ - return true; - } - } - - return false; - }; - - Polygon.prototype.edges = function(){ - var edges = this._edges; - if(!edges){ - edges = this._edges = []; - - var points = this.points(); - var L = points.length; - if(L){ - var prevPoint = points[0]; - var firstPoint = prevPoint; - - var point; - for(var i = 1 ; i < L ; i++){ - point = points[i]; - - edges.push(new Line(prevPoint.x, prevPoint.y, point.x, point.y)); - - prevPoint = point; - } - - if(L > 2){ - // point will have the last point - edges.push(new Line(point.x, point.y, firstPoint.x, firstPoint.y)); - } - } - } - - return edges; - }; - - Polygon.prototype.distance2 = function(p, k){ - var min = {cost: Infinity, dist2: Infinity}; //dist2(p, this.center(), k); - - this.edges().forEach(function(edge){ - var d = edge.distance2(p, k); - if(d.cost < min.cost){ - min = d; - } - }, this); - - return min; - }; - - Polygon.prototype.center = function(){ - var points = this.points(); - var x = 0; - var y = 0; - for(var i = 0, L = points.length ; i < L ; i++){ - var p = points[i]; - x += p.x; - y += p.y; - } - - return new Point(x / L, y / L); - }; - - // Adapted from http://stackoverflow.com/questions/217578/point-in-polygon-aka-hit-test (author Mecki) - Polygon.prototype.containsPoint = function(p){ - var bbox = this.bbox(); - if(!bbox.containsPoint(p)){ - return false; - } - - // "e" ensures the ray starts outside the polygon - var e = bbox.dx * 0.01; - var ray = new Line(bbox.x - e, p.y, p.x, p.y); - - var intersectCount = 0; - var edges = this.edges(); - edges.forEach(function(edge){ - if(edge.intersectsLine(ray)){ - intersectCount++; - } - }); - - // Inside if odd number of intersections - return (intersectCount & 1) === 1; - }; - - Polygon.prototype.bbox = function(){ - var bbox = this._bbox; - if(!bbox){ - var min, max; - - this - .points() - .forEach(function(point, index){ - if(min == null){ - min = {x: point.x, y: point.y}; - } else { - if(point.x < min.x){ - min.x = point.x; - } - - if(point.y < min.y){ - min.y = point.y; - } - } - - if(max == null){ - max = {x: point.x, y: point.y}; - } else { - if(point.x > max.x){ - max.x = point.x; - } - - if(point.y > max.y){ - max.y = point.y; - } - } - }); - - if(min){ - bbox = this._bbox = new pv.Shape.Rect(min.x, min.y, max.x - min.x, max.y - min.y); - } - } - - return bbox; - }; - -}()); - -(function(){ - - var Point = pv.Shape.Point; - var Line = pv.Shape.Line; - - pv.Shape.Rect = function(x, y, dx, dy){ - this.x = x || 0; - this.y = y || 0; - this.dx = dx || 0; - this.dy = dy || 0; - - // Ensure normalized - if(this.dx < 0){ - this.dx = -this.dx; - this.x = this.x - this.dx; - } - - if(this.dy < 0){ - this.dy = -this.dy; - this.y = this.y - this.dy; - } - - this.x2 = this.x + this.dx; - this.y2 = this.y + this.dy; - }; - - var Rect = pv.Shape.Rect; - - Rect.prototype = pv.extend(pv.Shape.Polygon); - - Rect.prototype.clone = function(){ - var r2 = Object.create(Rect.prototype); - r2.x = this.x; - r2.y = this.y; - r2.dx = this.dx; - r2.dy = this.dy; - r2.x2 = this.x2; - r2.y2 = this.y2; - - return r2; - }; - - Rect.prototype.apply = function(t){ - var x = t.x + (t.k * this.x); - var y = t.y + (t.k * this.y); - var dx = t.k * this.dx; - var dy = t.k * this.dy; - return new Rect(x, y, dx, dy); - }; - - Rect.prototype.containsPoint = function(p){ - return this.x <= p.x && p.x <= this.x2 && - this.y <= p.y && p.y <= this.y2; - }; - - Rect.prototype.intersectsRect = function(rect){ - return (this.x2 > rect.x ) && // Some intersection on X - (this.x < rect.x2) && - (this.y2 > rect.y ) && // Some intersection on Y - (this.y < rect.y2); - }; - - Rect.prototype.edges = function(){ - if(!this._edges){ - var x = this.x, - y = this.y, - x2 = this.x2, - y2 = this.y2; - - this._edges = [ - new Line(x, y, x2, y), - new Line(x2, y, x2, y2), - new Line(x2, y2, x, y2), - new Line(x, y2, x, y) - ]; - } - - return this._edges; - }; - - Rect.prototype.center = function(){ - return new Point(this.x + this.dx/2, this.y + this.dy/2); - }; - - Rect.prototype.points = function(){ - var points = this._points; - if(!points){ - var x = this.x, - y = this.y, - x2 = this.x2, - y2 = this.y2; - - points = this._points = [ - new Point(x, y ), - new Point(x2, y ), - new Point(x2, y2), - new Point(x, y2) - ]; - } - - return points; - }; - - Rect.prototype.bbox = function(){ - return this.clone(); - }; - -}());(function(){ - var Point = pv.Shape.Point; - var dist2 = pv.Shape.dist2; - var sqrt = Math.sqrt; - var abs = Math.abs; - var pow = Math.pow; - - pv.Shape.Circle = function(x, y, radius){ - this.x = x || 0; - this.y = y || 0; - this.radius = radius || 0; - }; - - var Circle = pv.Shape.Circle; - - Circle.prototype = pv.extend(pv.Shape); - - Circle.prototype.clone = function(){ - return new Circle(this.x, this.y, this.radius); - }; - - Circle.prototype.apply = function(t){ - var x = t.x + (t.k * this.x); - var y = t.y + (t.k * this.y); - var r = t.k * this.radius; - return new Circle(x, y, r); - }; - - // Adapted from http://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection - Circle.prototype.intersectsRect = function(rect){ - var dx2 = rect.dx / 2, - dy2 = rect.dy / 2, - r = this.radius; - - var circleDistX = abs(this.x - rect.x - dx2), - circleDistY = abs(this.y - rect.y - dy2); - - if ((circleDistX > dx2 + r) || - (circleDistY > dy2 + r)) { - return false; - } - - if (circleDistX <= dx2 || circleDistY <= dy2) { - return true; - } - - var sqCornerDistance = pow(circleDistX - dx2, 2) + - pow(circleDistY - dy2, 2); - - return sqCornerDistance <= r * r; - }; - - // Adapted from http://stackoverflow.com/questions/13053061/circle-line-intersection-points (author arne.b) - Circle.prototype.intersectLine = function(line, isInfiniteLine) { - // Line: A -> B - var baX = line.x2 - line.x; - var baY = line.y2 - line.y; - - var caX = this.x - line.x; - var caY = this.y - line.y; - - var ba2 = baX * baX + baY * baY; // square norm of ba - var bBy2 = baX * caX + baY * caY; // dot product of ba and ca - var r = this.radius; - var c = caX * caX + caY * caY - r * r; - - var pBy2 = bBy2 / ba2; - - var disc = pBy2 * pBy2 - c / ba2; - if (disc < 0) { - return; // no intersection - } - - // if disc == 0 ... dealt with later - var discSqrt = sqrt(disc); - var t1 = pBy2 - discSqrt; - var t2 = pBy2 + discSqrt; - - // t1 < 0 || t1 > 1 => p1 off the segment - - var ps = []; - if(isInfiniteLine || (t1 >= 0 && t1 <= 1)){ - ps.push(new Point(line.x + baX * t1, line.y + baY * t1)); - } - - if (disc !== 0) { // t1 != t2 - if(isInfiniteLine || (t2 >= 0 && t2 <= 1)){ - ps.push(new Point(line.x + baX * t2, line.y + baY * t2)); - } - } - - return ps; - }; - - Circle.prototype.points = function(){ - return [this.center()]; - }; - - Circle.prototype.center = function(){ - return new Point(this.x, this.y); - }; - - Circle.prototype.normal = function(at){ - return at.minus(this.x, this.y).norm(); - }; - - Circle.prototype.containsPoint = function(p){ - var dx = p.x - this.x, - dy = p.y - this.y, - r = this.radius; - - return dx * dx + dy * dy <= r * r; - }; - - // Distance (squared) to the border of the circle (inside or not) - // //or to the center of the circle, whichever is smaller - Circle.prototype.distance2 = function(p, k){ - var dx = p.x - this.x, - dy = p.y - this.y, - r = this.radius; - - //var dCenter = dist2(p, this, k); - - // The point at the Border of the circle, in the direction from c to p - var b = p.minus(this).norm().times(r).plus(this); - - var dBorder = dist2(p, b, k); - - return /*dCenter.cost < dBorder.cost ? dCenter : */dBorder; - }; - -}()); -(function(){ - - var Point = pv.Shape.Point; - var dist2 = pv.Shape.dist2; - var normalizeAngle = pv.Shape.normalizeAngle; - var atan2Norm = pv.Shape.atan2Norm; - - var cos = Math.cos; - var sin = Math.sin; - var sqrt = Math.sqrt; - - pv.Shape.Arc = function(x, y, radius, startAngle, angleSpan){ - this.x = x; - this.y = y; - this.radius = radius; - - this.startAngle = normalizeAngle(startAngle); - this.angleSpan = normalizeAngle(angleSpan); // always positive... - this.endAngle = this.startAngle + this.angleSpan; // may be > 2*pi - }; - - var Arc = pv.Shape.Arc; - - Arc.prototype = pv.extend(pv.Shape); - - Arc.prototype.hasArea = function(){ - return false; - }; - - Arc.prototype.clone = function(){ - var arc = Object.create(Arc.prototype); - var me = this; - arc.x = me.x; - arc.y = me.y; - arc.radius = me.radius; - arc.startAngle = me.startAngle; - arc.angleSpan = me.angleSpan; - arc.endAngle = me.endAngle; - return arc; - }; - - Arc.prototype.apply = function(t){ - var x = t.x + (t.k * this.x); - var y = t.y + (t.k * this.y); - var r = t.k * this.radius; - return new Arc(x, y, r, this.startAngle, this.angleSpan); - }; - - Arc.prototype.containsPoint = function(p){ - var dx = p.x - this.x; - var dy = p.y - this.y; - var r = sqrt(dx*dx + dy*dy); - - if(Math.abs(r - this.radius) <= 1e-10){ - var a = atan2Norm(dy, dx); - return this.startAngle <= a && a <= this.endAngle; - } - - return false; - }; - - Arc.prototype.intersectsRect = function(rect) { - var i, L; - - // I - Any endpoint is inside the rect? - var points = this.points(); - var L = points.length; - for(i = 0 ; i < L ; i++){ - if(points[i].intersectsRect(rect)){ - return true; - } - } - - // II - Any rect edge intersects the arc? - var edges = rect.edges(); - L = edges.length; - for(i = 0 ; i < L ; i++){ - if(this.intersectLine(edges[i])){ - return true; - } - } - - return false; - }; - - var circleIntersectLine = pv.Shape.Circle.prototype.intersectLine; - - Arc.prototype.intersectLine = function(line, isInfiniteLine) { - var ps = circleIntersectLine.call(this, line, isInfiniteLine); - if(ps){ - // Filter ps belonging to the arc - ps = ps.filter(function(p){ return this.containsPoint(p); }, this); - if(ps.length){ - return ps; - } - } - }; - - Arc.prototype.points = function(){ - var x = this.x; - var y = this.y; - var r = this.radius; - var ai = this.startAngle; - var af = this.endAngle; - - return [ - new Point(x + r * cos(ai), y + r * sin(ai)), - new Point(x + r * cos(af), y + r * sin(af)) - ]; - }; - - Arc.prototype.center = function(){ - var x = this.x; - var y = this.y; - var r = this.radius; - var am = (this.startAngle + this.endAngle) / 2; - - return new Point(x + r * cos(am), y + r * sin(am)); - }; - - Arc.prototype.normal = function(at, shapeCenter){ - var norm = at.minus(this.x, this.y).norm(); - - // If shapeCenter point is specified, - // return the norm direction that - // points to the outside of the shape - if(shapeCenter){ - var outside = this.center().minus(shapeCenter); - if(outside.dot(norm) < 0){ - // opposite directions - norm = norm.times(-1); - } - } - - return norm; - }; - - // Distance (squared) to the border of the Arc (inside or not) - Arc.prototype.distance2 = function(p, k){ - var dx = p.x - this.x; - var dy = p.y - this.y; - var a = atan2Norm(dy, dx); // between 0 and 2*pi - - if(this.startAngle <= a && a <= this.endAngle){ - // Within angle span - - // The point at the Border of the circle, in the direction from c to p - var b = new Point( - this.x + this.radius * cos(a), - this.y + this.radius * sin(a)); - - return dist2(p, b, k); - } - - // Smallest distance to one of the two end points - var points = this.points(); - var d1 = dist2(p, points[0], k); - var d2 = dist2(p, points[1], k); - return d1.cost < d2.cost ? d1 : d2; - }; - -}()); -(function(){ - - var Arc = pv.Shape.Arc; - var Line = pv.Shape.Line; - var Point = pv.Shape.Point; - - var cos = Math.cos; - var sin = Math.sin; - var sqrt = Math.sqrt; - var atan2Norm = pv.Shape.atan2Norm; - var normalizeAngle = pv.Shape.normalizeAngle; - - pv.Shape.Wedge = function(x, y, innerRadius, outerRadius, startAngle, angleSpan){ - this.x = x; - this.y = y; - this.innerRadius = innerRadius; - this.outerRadius = outerRadius; - - this.startAngle = normalizeAngle(startAngle); - this.angleSpan = normalizeAngle(angleSpan); // always positive... - this.endAngle = this.startAngle + this.angleSpan; // may be > 2*pi - }; - - var Wedge = pv.Shape.Wedge; - - Wedge.prototype = pv.extend(pv.Shape); - - Wedge.prototype.clone = function(){ - return new Wedge( - this.x, this.y, this.innerRadius, - this.outerRadius, this.startAngle, this.angleSpan); - }; - - Wedge.prototype.apply = function(t){ - var x = t.x + (t.k * this.x); - var y = t.y + (t.k * this.y); - var ir = t.k * this.innerRadius; - var or = t.k * this.outerRadius; - return new Wedge(x, y, ir, or, this.startAngle, this.angleSpan); - }; - - Wedge.prototype.containsPoint = function(p){ - var dx = p.x - this.x; - var dy = p.y - this.y ; - var r = sqrt(dx*dx + dy*dy); - if(r >= this.innerRadius && r <= this.outerRadius){ - var a = atan2Norm(dy, dx); // between -pi and pi -> 0 - 2*pi - return this.startAngle <= a && a <= this.endAngle; - } - - return false; - }; - - Wedge.prototype.intersectsRect = function(rect){ - var i, L; - - // I - Any point of the wedge is inside the rect? - var points = this.points(); - - L = points.length; - for(i = 0 ; i < L ; i++){ - if(points[i].intersectsRect(rect)){ - return true; - } - } - - // II - Any point of the rect inside the wedge? - points = rect.points(); - L = points.length; - for(i = 0 ; i < L ; i++){ - if(this.containsPoint(points[i])){ - return true; - } - } - - // III - Any edge intersects the rect? - var edges = this.edges(); - L = edges.length; - for(i = 0 ; i < L ; i++){ - if(edges[i].intersectsRect(rect)){ - return true; - } - } - - return false; - }; - - Wedge.prototype.points = function(){ - if(!this._points){ - this.edges(); - } - - return this._points; - }; - - Wedge.prototype.edges = function(){ - var edges = this._edges; - if(!edges){ - var x = this.x; - var y = this.y; - var ir = this.innerRadius; - var or = this.outerRadius; - var ai = this.startAngle; - var af = this.endAngle; - var aa = this.angleSpan; - var cai = cos(ai); - var sai = sin(ai); - var caf = cos(af); - var saf = sin(af); - - var pii, pfi; - if(ir > 0){ - pii = new Point(x + ir * cai, y + ir * sai); - pfi = new Point(x + ir * caf, y + ir * saf); - } else { - pii = pfi = new Point(x, y); - } - - var pio = new Point(x + or * cai, y + or * sai); - var pfo = new Point(x + or * caf, y + or * saf); - - edges = this._edges = []; - - if(ir > 0){ - edges.push(new Arc(x, y, ir, ai, aa)); - } - - edges.push( - new Line(pii.x, pii.y, pio.x, pio.y), - new Arc(x, y, or, ai, aa), - new Line(pfi.x, pfi.y, pfo.x, pfo.y)); - - var points = this._points = [pii, pio, pfo]; - if(ir > 0){ - points.push(pfi); - } - } - - return edges; - }; - - // Distance (squared) to the border of the Wedge, - // // or to its center, whichever is smaller. - Wedge.prototype.distance2 = function(p, k){ - var min = {cost: Infinity, dist2: Infinity}; //dist2(p, this.center(), k); - - this.edges().forEach(function(edge){ - var d = edge.distance2(p, k); - if(d.cost < min.cost){ - min = d; - } - }); - - return min; - }; - - Wedge.prototype.center = function(){ - var midAngle = (this.startAngle + this.endAngle)/2; - var midRadius = (this.innerRadius + this.outerRadius)/2; - return new Point( - this.x + midRadius * cos(midAngle), - this.y + midRadius * sin(midAngle)); - }; -}()); -/** - * Returns the {@link pv.Color} for the specified color format string. Colors - * may have an associated opacity, or alpha channel. Color formats are specified - * by CSS Color Modular Level 3, using either in RGB or HSL color space. For - * example:

    - * - *
  • #f00 // #rgb - *
  • #ff0000 // #rrggbb - *
  • rgb(255, 0, 0) - *
  • rgb(100%, 0%, 0%) - *
  • hsl(0, 100%, 50%) - *
  • rgba(0, 0, 255, 0.5) - *
  • hsla(120, 100%, 50%, 1) - * - *
The SVG 1.0 color keywords names are also supported, such as "aliceblue" - * and "yellowgreen". The "transparent" keyword is supported for fully- - * transparent black. - * - *

If the format argument is already an instance of Color, - * the argument is returned with no further processing. - * - * @param {string} format the color specification string, such as "#f00". - * @returns {pv.Color} the corresponding Color. - * @see SVG color - * keywords - * @see CSS3 color module - */ -pv.color = function(format) { - if (format.rgb) return format.rgb(); - - /* Handle hsl, rgb. */ - var m1 = /([a-z]+)\((.*)\)/i.exec(format); - if (m1) { - var m2 = m1[2].split(","), a = 1; - switch (m1[1]) { - case "hsla": - case "rgba": { - a = parseFloat(m2[3]); - if (!a) return pv.Color.transparent; - break; - } - } - switch (m1[1]) { - case "hsla": - case "hsl": { - var h = parseFloat(m2[0]), // degrees - s = parseFloat(m2[1]) / 100, // percentage - l = parseFloat(m2[2]) / 100; // percentage - return (new pv.Color.Hsl(h, s, l, a)).rgb(); - } - case "rgba": - case "rgb": { - function parse(c) { // either integer or percentage - var f = parseFloat(c); - return (c[c.length - 1] == '%') ? Math.round(f * 2.55) : f; - } - var r = parse(m2[0]), g = parse(m2[1]), b = parse(m2[2]); - return pv.rgb(r, g, b, a); - } - } - } - - /* Named colors. */ - var named = pv.Color.names[format]; - if (named) return named; - - /* Hexadecimal colors: #rgb and #rrggbb. */ - if (format.charAt(0) == "#") { - var r, g, b; - if (format.length == 4) { - r = format.charAt(1); r += r; - g = format.charAt(2); g += g; - b = format.charAt(3); b += b; - } else if (format.length == 7) { - r = format.substring(1, 3); - g = format.substring(3, 5); - b = format.substring(5, 7); - } - return pv.rgb(parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), 1); - } - - /* Otherwise, pass-through unsupported colors. */ - return new pv.Color(format, 1); -}; - -/** - * Constructs a color with the specified color format string and opacity. This - * constructor should not be invoked directly; use {@link pv.color} instead. - * - * @class Represents an abstract (possibly translucent) color. The color is - * divided into two parts: the color attribute, an opaque color format - * string, and the opacity attribute, a float in [0, 1]. The color - * space is dependent on the implementing class; all colors support the - * {@link #rgb} method to convert to RGB color space for interpolation. - * - *

See also the Color guide. - * - * @param {string} color an opaque color format string, such as "#f00". - * @param {number} opacity the opacity, in [0,1]. - * @see pv.color - */ -pv.Color = function(color, opacity) { - /** - * An opaque color format string, such as "#f00". - * - * @type string - * @see SVG color - * keywords - * @see CSS3 color module - */ - this.color = color; - - /** - * The opacity, a float in [0, 1]. - * - * @type number - */ - this.opacity = opacity; - - this.key = "solid " + color + " alpha(" + opacity + ")"; -}; - -/** - * Returns an equivalent color in the HSL color space. - * - * @returns {pv.Color.Hsl} an HSL color. - */ -pv.Color.prototype.hsl = function() { - return this.rgb().hsl(); -}; - -/** - * Returns a new color that is a brighter version of this color. The behavior of - * this method may vary slightly depending on the underlying color space. - * Although brighter and darker are inverse operations, the results of a series - * of invocations of these two methods might be inconsistent because of rounding - * errors. - * - * @param [k] {number} an optional scale factor; defaults to 1. - * @see #darker - * @returns {pv.Color} a brighter color. - */ -pv.Color.prototype.brighter = function(k) { - return this.rgb().brighter(k); -}; - -/** - * Returns a new color that is a brighter version of this color. The behavior of - * this method may vary slightly depending on the underlying color space. - * Although brighter and darker are inverse operations, the results of a series - * of invocations of these two methods might be inconsistent because of rounding - * errors. - * - * @param [k] {number} an optional scale factor; defaults to 1. - * @see #brighter - * @returns {pv.Color} a darker color. - */ -pv.Color.prototype.darker = function(k) { - return this.rgb().darker(k); -}; - -/** - * Constructs a new RGB color with the specified channel values. - * - * @param {number} r the red channel, an integer in [0,255]. - * @param {number} g the green channel, an integer in [0,255]. - * @param {number} b the blue channel, an integer in [0,255]. - * @param {number} [a] the alpha channel, a float in [0,1]. - * @returns pv.Color.Rgb - */ -pv.rgb = function(r, g, b, a) { - return new pv.Color.Rgb(r, g, b, (arguments.length == 4) ? a : 1); -}; - -/** - * Constructs a new RGB color with the specified channel values. - * - * @class Represents a color in RGB space. - * - * @param {number} r the red channel, an integer in [0,255]. - * @param {number} g the green channel, an integer in [0,255]. - * @param {number} b the blue channel, an integer in [0,255]. - * @param {number} a the alpha channel, a float in [0,1]. - * @extends pv.Color - */ -pv.Color.Rgb = function(r, g, b, a) { - pv.Color.call(this, a ? ("rgb(" + r + "," + g + "," + b + ")") : "none", a); - - /** - * The red channel, an integer in [0, 255]. - * - * @type number - */ - this.r = r; - - /** - * The green channel, an integer in [0, 255]. - * - * @type number - */ - this.g = g; - - /** - * The blue channel, an integer in [0, 255]. - * - * @type number - */ - this.b = b; - - /** - * The alpha channel, a float in [0, 1]. - * - * @type number - */ - this.a = a; -}; -pv.Color.Rgb.prototype = pv.extend(pv.Color); - -/** - * Constructs a new RGB color with the same green, blue and alpha channels as - * this color, with the specified red channel. - * - * @param {number} r the red channel, an integer in [0,255]. - */ -pv.Color.Rgb.prototype.red = function(r) { - return pv.rgb(r, this.g, this.b, this.a); -}; - -/** - * Constructs a new RGB color with the same red, blue and alpha channels as this - * color, with the specified green channel. - * - * @param {number} g the green channel, an integer in [0,255]. - */ -pv.Color.Rgb.prototype.green = function(g) { - return pv.rgb(this.r, g, this.b, this.a); -}; - -/** - * Constructs a new RGB color with the same red, green and alpha channels as - * this color, with the specified blue channel. - * - * @param {number} b the blue channel, an integer in [0,255]. - */ -pv.Color.Rgb.prototype.blue = function(b) { - return pv.rgb(this.r, this.g, b, this.a); -}; - -/** - * Constructs a new RGB color with the same red, green and blue channels as this - * color, with the specified alpha channel. - * - * @param {number} a the alpha channel, a float in [0,1]. - */ -pv.Color.Rgb.prototype.alpha = function(a) { - return pv.rgb(this.r, this.g, this.b, a); -}; - -/** - * Returns the RGB color equivalent to this color. This method is abstract and - * must be implemented by subclasses. - * - * @returns {pv.Color.Rgb} an RGB color. - * @function - * @name pv.Color.prototype.rgb - */ - -/** - * Returns this. - * - * @returns {pv.Color.Rgb} this. - */ -pv.Color.Rgb.prototype.rgb = function() { return this; }; - -/** - * Returns a new color that is a brighter version of this color. This method - * applies an arbitrary scale factor to each of the three RGB components of this - * color to create a brighter version of this color. Although brighter and - * darker are inverse operations, the results of a series of invocations of - * these two methods might be inconsistent because of rounding errors. - * - * @param [k] {number} an optional scale factor; defaults to 1. - * @see #darker - * @returns {pv.Color.Rgb} a brighter color. - */ -pv.Color.Rgb.prototype.brighter = function(k) { - k = Math.pow(0.7, arguments.length ? k : 1); - var r = this.r, g = this.g, b = this.b, i = 30; - if (!r && !g && !b) return pv.rgb(i, i, i, this.a); - if (r && (r < i)) r = i; - if (g && (g < i)) g = i; - if (b && (b < i)) b = i; - return pv.rgb( - Math.min(255, Math.floor(r / k)), - Math.min(255, Math.floor(g / k)), - Math.min(255, Math.floor(b / k)), - this.a); -}; - -/** - * Returns a new color that is a darker version of this color. This method - * applies an arbitrary scale factor to each of the three RGB components of this - * color to create a darker version of this color. Although brighter and darker - * are inverse operations, the results of a series of invocations of these two - * methods might be inconsistent because of rounding errors. - * - * @param [k] {number} an optional scale factor; defaults to 1. - * @see #brighter - * @returns {pv.Color.Rgb} a darker color. - */ -pv.Color.Rgb.prototype.darker = function(k) { - k = Math.pow(0.7, arguments.length ? k : 1); - return pv.rgb( - Math.max(0, Math.floor(k * this.r)), - Math.max(0, Math.floor(k * this.g)), - Math.max(0, Math.floor(k * this.b)), - this.a); -}; - -/** - * Converts an RGB color value to HSL. - * Conversion formula adapted from http://en.wikipedia.org/wiki/HSL_color_space. - * - * (Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript) - * - * @returns pv.Color.Hsl - */ -pv.Color.Rgb.prototype.hsl = function(){ - var r = this.r / 255; - var g = this.g / 255; - var b = this.b / 255; - - var max = Math.max(r, g, b); - var min = Math.min(r, g, b); - - var l = (max + min) / 2; - var h, s; - - 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 pv.hsl(h * 360, s, l, this.a); -}; - -/** - * Constructs a new HSL color with the specified values. - * - * @param {number} h the hue, an integer in [0, 360]. - * @param {number} s the saturation, a float in [0, 1]. - * @param {number} l the lightness, a float in [0, 1]. - * @param {number} [a] the opacity, a float in [0, 1]. - * @returns pv.Color.Hsl - */ -pv.hsl = function(h, s, l, a) { - return new pv.Color.Hsl(h, s, l, (arguments.length == 4) ? a : 1); -}; - -/** - * Constructs a new HSL color with the specified values. - * - * @class Represents a color in HSL space. - * - * @param {number} h the hue, an integer in [0, 360]. - * @param {number} s the saturation, a float in [0, 1]. - * @param {number} l the lightness, a float in [0, 1]. - * @param {number} a the opacity, a float in [0, 1]. - * @extends pv.Color - */ -pv.Color.Hsl = function(h, s, l, a) { - pv.Color.call(this, "hsl(" + h + "," + (s * 100) + "%," + (l * 100) + "%)", a); - - /** - * The hue, an integer in [0, 360]. - * - * @type number - */ - this.h = h; - - /** - * The saturation, a float in [0, 1]. - * - * @type number - */ - this.s = s; - - /** - * The lightness, a float in [0, 1]. - * - * @type number - */ - this.l = l; - - /** - * The opacity, a float in [0, 1]. - * - * @type number - */ - this.a = a; -}; -pv.Color.Hsl.prototype = pv.extend(pv.Color); - -/** - * Returns this. - * - * @returns {pv.Color.Hsl} this. - */ -pv.Color.Hsl.prototype.hsl = function() { return this; }; - - -/** - * Constructs a new HSL color with the same saturation, lightness and alpha as - * this color, and the specified hue. - * - * @param {number} h the hue, an integer in [0, 360]. - */ -pv.Color.Hsl.prototype.hue = function(h) { - return pv.hsl(h, this.s, this.l, this.a); -}; - -/** - * Constructs a new HSL color with the same hue, lightness and alpha as this - * color, and the specified saturation. - * - * @param {number} s the saturation, a float in [0, 1]. - */ -pv.Color.Hsl.prototype.saturation = function(s) { - return pv.hsl(this.h, s, this.l, this.a); -}; - -/** - * Constructs a new HSL color with the same hue, saturation and alpha as this - * color, and the specified lightness. - * - * @param {number} l the lightness, a float in [0, 1]. - */ -pv.Color.Hsl.prototype.lightness = function(l) { - return pv.hsl(this.h, this.s, l, this.a); -}; - -/** - * Constructs a new HSL color with the same hue, saturation and lightness as - * this color, and the specified alpha. - * - * @param {number} a the opacity, a float in [0, 1]. - */ -pv.Color.Hsl.prototype.alpha = function(a) { - return pv.hsl(this.h, this.s, this.l, a); -}; - -/** - * Returns the RGB color equivalent to this HSL color. - * - * @returns {pv.Color.Rgb} an RGB color. - */ -pv.Color.Hsl.prototype.rgb = function() { - var h = this.h, s = this.s, l = this.l; - - /* Some simple corrections for h, s and l. */ - h = h % 360; if (h < 0) h += 360; - s = Math.max(0, Math.min(s, 1)); - l = Math.max(0, Math.min(l, 1)); - - /* From FvD 13.37, CSS Color Module Level 3 */ - var m2 = (l <= .5) ? (l * (1 + s)) : (l + s - l * s); - var m1 = 2 * l - m2; - function v(h) { - if (h > 360) h -= 360; - else if (h < 0) h += 360; - if (h < 60) return m1 + (m2 - m1) * h / 60; - if (h < 180) return m2; - if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; - return m1; - } - function vv(h) { - return Math.round(v(h) * 255); - } - - return pv.rgb(vv(h + 120), vv(h), vv(h - 120), this.a); -}; - -/** - * @private SVG color keywords, per CSS Color Module Level 3. - * - * @see SVG color - * keywords - */ -pv.Color.names = { - aliceblue: "#f0f8ff", - antiquewhite: "#faebd7", - aqua: "#00ffff", - aquamarine: "#7fffd4", - azure: "#f0ffff", - beige: "#f5f5dc", - bisque: "#ffe4c4", - black: "#000000", - blanchedalmond: "#ffebcd", - blue: "#0000ff", - blueviolet: "#8a2be2", - brown: "#a52a2a", - burlywood: "#deb887", - cadetblue: "#5f9ea0", - chartreuse: "#7fff00", - chocolate: "#d2691e", - coral: "#ff7f50", - cornflowerblue: "#6495ed", - cornsilk: "#fff8dc", - crimson: "#dc143c", - cyan: "#00ffff", - darkblue: "#00008b", - darkcyan: "#008b8b", - darkgoldenrod: "#b8860b", - darkgray: "#a9a9a9", - darkgreen: "#006400", - darkgrey: "#a9a9a9", - darkkhaki: "#bdb76b", - darkmagenta: "#8b008b", - darkolivegreen: "#556b2f", - darkorange: "#ff8c00", - darkorchid: "#9932cc", - darkred: "#8b0000", - darksalmon: "#e9967a", - darkseagreen: "#8fbc8f", - darkslateblue: "#483d8b", - darkslategray: "#2f4f4f", - darkslategrey: "#2f4f4f", - darkturquoise: "#00ced1", - darkviolet: "#9400d3", - deeppink: "#ff1493", - deepskyblue: "#00bfff", - dimgray: "#696969", - dimgrey: "#696969", - dodgerblue: "#1e90ff", - firebrick: "#b22222", - floralwhite: "#fffaf0", - forestgreen: "#228b22", - fuchsia: "#ff00ff", - gainsboro: "#dcdcdc", - ghostwhite: "#f8f8ff", - gold: "#ffd700", - goldenrod: "#daa520", - gray: "#808080", - green: "#008000", - greenyellow: "#adff2f", - grey: "#808080", - honeydew: "#f0fff0", - hotpink: "#ff69b4", - indianred: "#cd5c5c", - indigo: "#4b0082", - ivory: "#fffff0", - khaki: "#f0e68c", - lavender: "#e6e6fa", - lavenderblush: "#fff0f5", - lawngreen: "#7cfc00", - lemonchiffon: "#fffacd", - lightblue: "#add8e6", - lightcoral: "#f08080", - lightcyan: "#e0ffff", - lightgoldenrodyellow: "#fafad2", - lightgray: "#d3d3d3", - lightgreen: "#90ee90", - lightgrey: "#d3d3d3", - lightpink: "#ffb6c1", - lightsalmon: "#ffa07a", - lightseagreen: "#20b2aa", - lightskyblue: "#87cefa", - lightslategray: "#778899", - lightslategrey: "#778899", - lightsteelblue: "#b0c4de", - lightyellow: "#ffffe0", - lime: "#00ff00", - limegreen: "#32cd32", - linen: "#faf0e6", - magenta: "#ff00ff", - maroon: "#800000", - mediumaquamarine: "#66cdaa", - mediumblue: "#0000cd", - mediumorchid: "#ba55d3", - mediumpurple: "#9370db", - mediumseagreen: "#3cb371", - mediumslateblue: "#7b68ee", - mediumspringgreen: "#00fa9a", - mediumturquoise: "#48d1cc", - mediumvioletred: "#c71585", - midnightblue: "#191970", - mintcream: "#f5fffa", - mistyrose: "#ffe4e1", - moccasin: "#ffe4b5", - navajowhite: "#ffdead", - navy: "#000080", - oldlace: "#fdf5e6", - olive: "#808000", - olivedrab: "#6b8e23", - orange: "#ffa500", - orangered: "#ff4500", - orchid: "#da70d6", - palegoldenrod: "#eee8aa", - palegreen: "#98fb98", - paleturquoise: "#afeeee", - palevioletred: "#db7093", - papayawhip: "#ffefd5", - peachpuff: "#ffdab9", - peru: "#cd853f", - pink: "#ffc0cb", - plum: "#dda0dd", - powderblue: "#b0e0e6", - purple: "#800080", - red: "#ff0000", - rosybrown: "#bc8f8f", - royalblue: "#4169e1", - saddlebrown: "#8b4513", - salmon: "#fa8072", - sandybrown: "#f4a460", - seagreen: "#2e8b57", - seashell: "#fff5ee", - sienna: "#a0522d", - silver: "#c0c0c0", - skyblue: "#87ceeb", - slateblue: "#6a5acd", - slategray: "#708090", - slategrey: "#708090", - snow: "#fffafa", - springgreen: "#00ff7f", - steelblue: "#4682b4", - tan: "#d2b48c", - teal: "#008080", - thistle: "#d8bfd8", - tomato: "#ff6347", - turquoise: "#40e0d0", - violet: "#ee82ee", - wheat: "#f5deb3", - white: "#ffffff", - whitesmoke: "#f5f5f5", - yellow: "#ffff00", - yellowgreen: "#9acd32", - transparent: pv.Color.transparent = pv.rgb(0, 0, 0, 0) -}; - -/* Initialized named colors. */ -(function() { - var names = pv.Color.names; - names.none = names.transparent; - for (var name in names) names[name] = pv.color(names[name]); -})(); -/** - * Returns a new categorical color encoding using the specified colors. The - * arguments to this method are an array of colors; see {@link pv.color}. For - * example, to create a categorical color encoding using the species - * attribute: - * - *

pv.colors("red", "green", "blue").by(function(d) d.species)
- * - * The result of this expression can be used as a fill- or stroke-style - * property. This assumes that the data's species attribute is a - * string. - * - * @param {string} colors... categorical colors. - * @see pv.Scale.ordinal - * @returns {pv.Scale.ordinal} an ordinal color scale. - */ -pv.colors = function() { - var scale = pv.Scale.ordinal(); - scale.range.apply(scale, arguments); - return scale; -}; - -/** - * A collection of standard color palettes for categorical encoding. - * - * @namespace A collection of standard color palettes for categorical encoding. - */ -pv.Colors = {}; - -/** - * Returns a new 10-color scheme. The arguments to this constructor are - * optional, and equivalent to calling {@link pv.Scale.OrdinalScale#domain}. The - * following colors are used: - * - *
#1f77b4
- *
#ff7f0e
- *
#2ca02c
- *
#d62728
- *
#9467bd
- *
#8c564b
- *
#e377c2
- *
#7f7f7f
- *
#bcbd22
- *
#17becf
- * - * @param {number...} domain... domain values. - * @returns {pv.Scale.ordinal} a new ordinal color scale. - * @see pv.color - */ -pv.Colors.category10 = function() { - var scale = pv.colors( - "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", - "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"); - scale.domain.apply(scale, arguments); - return scale; -}; - -/** - * Returns a new 20-color scheme. The arguments to this constructor are - * optional, and equivalent to calling {@link pv.Scale.OrdinalScale#domain}. The - * following colors are used: - * - *
#1f77b4
- *
#aec7e8
- *
#ff7f0e
- *
#ffbb78
- *
#2ca02c
- *
#98df8a
- *
#d62728
- *
#ff9896
- *
#9467bd
- *
#c5b0d5
- *
#8c564b
- *
#c49c94
- *
#e377c2
- *
#f7b6d2
- *
#7f7f7f
- *
#c7c7c7
- *
#bcbd22
- *
#dbdb8d
- *
#17becf
- *
#9edae5
- * - * @param {number...} domain... domain values. - * @returns {pv.Scale.ordinal} a new ordinal color scale. - * @see pv.color -*/ -pv.Colors.category20 = function() { - var scale = pv.colors( - "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", - "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", - "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", - "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5"); - scale.domain.apply(scale, arguments); - return scale; -}; - -/** - * Returns a new alternative 19-color scheme. The arguments to this constructor - * are optional, and equivalent to calling - * {@link pv.Scale.OrdinalScale#domain}. The following colors are used: - * - *
#9c9ede
- *
#7375b5
- *
#4a5584
- *
#cedb9c
- *
#b5cf6b
- *
#8ca252
- *
#637939
- *
#e7cb94
- *
#e7ba52
- *
#bd9e39
- *
#8c6d31
- *
#e7969c
- *
#d6616b
- *
#ad494a
- *
#843c39
- *
#de9ed6
- *
#ce6dbd
- *
#a55194
- *
#7b4173
- * - * @param {number...} domain... domain values. - * @returns {pv.Scale.ordinal} a new ordinal color scale. - * @see pv.color - */ -pv.Colors.category19 = function() { - var scale = pv.colors( - "#9c9ede", "#7375b5", "#4a5584", "#cedb9c", "#b5cf6b", - "#8ca252", "#637939", "#e7cb94", "#e7ba52", "#bd9e39", - "#8c6d31", "#e7969c", "#d6616b", "#ad494a", "#843c39", - "#de9ed6", "#ce6dbd", "#a55194", "#7b4173"); - scale.domain.apply(scale, arguments); - return scale; -}; -(function() { - /* Adapted from https://gitorious.org/~brendansterne/protovis/brendansternes-protovis */ - - /** - * TBD Returns the {@link pv.FillStyle} for the specified format string. - * For example: - *
    - *
  • linear-gradient(angle-spec, white, black)
  • - *
  • red
  • - *
  • linear-gradient(to top, white, red 40%, black 100%)
  • - *
  • linear-gradient(90deg, white, red 40%, black 100%)
  • - *
- * - * @param {string} format the gradient specification string. - * @returns {pv.FillStyle} the corresponding FillStyle. - * @see CSS3 Gradients - */ - pv.fillStyle = function(format) { - /* A FillStyle object? */ - if (format.type) { - return format; - } - - /* A Color object? */ - if (format.rgb) { - return new pv.FillStyle.Solid(format.color, format.opacity); - } - - /* A gradient spec. ? */ - var match = /^\s*([a-z\-]+)\(\s*(.*?)\s*\)\s*$/.exec(format); - if (match) { - switch (match[1]) { - case "linear-gradient": return parseLinearGradient(match[2]); - case "radial-gradient": return parseRadialGradient(match[2]); - } - } - - // Default to solid fill - return new pv.FillStyle.Solid(pv.color(format)); - }; - - var keyAnglesDeg = { - top: 0, - 'top right': 45, - right: 90, - 'bottom right': 135, - bottom: 180, - 'bottom left': 225, - left: 270, - 'top left': 315 - }; - - /* - * linear-gradient() := [, ], ... - * - * := | - * -> default is "to bottom" - * - * := to (top | bottom) || (left | right) - * top -> 0deg - * right -> 90deg - * bottom -> 180deg - * left -> 270deg - * - * := [deg] - * - * examples: - * "bottom~white to top~black" - * linear-gradient(to top, white, black) - * - * "bottom-right~white to top-left~black" - * linear-gradient(to top left, white, black) - */ - function parseLinearGradient(text) { - var terms = parseText(text); - if (!terms.length) { - return null; - } - - var angle = Math.PI; - var keyAngle; - var m, f; - var term = terms[0]; - if (term.indexOf('to ') === 0) { - // to side / corner - m = /^to\s+(?:((top|bottom)(?:\s+(left|right))?)|((left|right)(?:\\s+(top|bottom))?))$/ - .exec(term); - if (m) { - if (m[1]) { - // (top|bottom)(?:\s+(left|right))? - keyAngle = m[2]; - if(m[3]){ - keyAngle += ' ' + m[3]; - } - } else { // m[4] - // (left|right)(?:\\s+(top|bottom))? - keyAngle = m[5]; - if(m[6]){ - keyAngle = m[6] + ' ' + keyAngle; - } - } - - angle = pv.radians(keyAnglesDeg[keyAngle]); - - terms.shift(); - } - } else { - // Check number - f = parseFloat(term); // tolerates text suffixes - if (!isNaN(f)) { - angle = f; - - // Check the unit - if (/^.*?deg$/.test(term)) { - angle = pv.radians(angle); - } - terms.shift(); - } - } - - var stops = parseStops(terms); - switch (stops.length) { - case 0: return null; - case 1: return new pv.FillStyle.Solid(stops[0].color, 1); - } - - return new pv.FillStyle.LinearGradient(angle, stops, text); - } - - /* - * radial-gradient() - * - * := [, ], ... - * - * not implemented: - * := at | - * at | - * at - * - * := center | top left | top right | bottom left | bottom right | ... - * -> default = "center" - * - * := % - * - * examples: - * radial-gradient(at center, white, black) - */ - function parseRadialGradient(text) { - var terms = parseText(text); - if (!terms.length) { - return null; - } - - var stops = parseStops(terms); - switch (stops.length) { - case 0: return null; - case 1: return new pv.FillStyle.Solid(stops[0].color, 1); - } - - return new pv.FillStyle.RadialGradient(50, 50, stops, text); - } - - function parseText(text){ - var colorFuns = {}; - var colorFunId = 0; - - text = text.replace(/\b\w+?\(.*?\)/g, function($0){ - var id = '__color' + (colorFunId++); - colorFuns[id] = $0; - return id; - }); - - var terms = text.split(/\s*,\s*/); - if (!terms.length) { - return null; - } - - // Re-insert color functions - if(colorFunId){ - terms.forEach(function(id, index){ - if(colorFuns.hasOwnProperty(id)){ - terms[index] = colorFuns[id]; - } - }); - } - - return terms; - } - - /* - * COLOR STOPS - * := [] - * - * := % - * - * := rgb() | rgba() | hsl() | hsla() | white | ... - */ - function parseStops(terms) { - var stops = []; - var minOffsetPercent = +Infinity; - var maxOffsetPercent = -Infinity; - var pendingOffsetStops = []; - - function processPendingStops(lastOffset) { - var count = pendingOffsetStops.length; - if (count) { - var firstOffset = maxOffsetPercent; - var step = (lastOffset - firstOffset) / (count + 1); - for (var i = 0; i < count; i++) { - firstOffset += step; - pendingOffsetStops[i].offset = firstOffset; - } - - pendingOffsetStops.length = 0; - } - } - - var i = 0; - var T = terms.length; - while (i < T) { - var term = terms[i++]; - - var m = /^(.+?)\s*([+\-]?[e\.\d]+%)?$/i.exec(term); - if (m) { - var stop = { - color: pv.color(m[1]) - }; - - var offsetPercent = parseFloat(m[2]); // tolerates text suffixes - if (isNaN(offsetPercent)) { - if (!stops.length) { - offsetPercent = 0; - } else if (i === T) { // last one defaults to "100"... - offsetPercent = Math.max(maxOffsetPercent, 100); - } - } - - stops.push(stop); - - if (isNaN(offsetPercent)) { - pendingOffsetStops.push(stop); - } else { - stop.offset = offsetPercent; - - processPendingStops(offsetPercent); - - if (offsetPercent > maxOffsetPercent) { - // Record maximum value so far - maxOffsetPercent = offsetPercent; - } else if (offsetPercent < maxOffsetPercent) { - // Cannot go backwards - offsetPercent = maxOffsetPercent; - } - - if (offsetPercent < minOffsetPercent) { - minOffsetPercent = offsetPercent; - } - } - } - } - - if (stops.length >= 2 && - (minOffsetPercent < 0 || maxOffsetPercent > 100)) { - // Normalize < 0 and > 100 values, cause SVG does not support them - // TODO: what about the interpretation of an end < 100 or begin > 0? - var colorDomain = []; - var colorRange = []; - stops.forEach(function(stop) { - colorDomain.push(stop.offset); - colorRange.push(stop.color); - }); - - var colorScale = pv.scale.linear() - .domain(colorDomain) - .range(colorRange); - - if (minOffsetPercent < 0) { - while (stops.length && stops[0].offset <= 0) { - stops.shift(); - } - - stops.unshift({ - offset: 0, - color: colorScale(0) - }); - } - - if (maxOffsetPercent > 100) { - - while (stops.length && stops[stops.length - 1].offset >= 100) { - stops.pop(); - } - - stops.push({ - offset: 100, - color: colorScale(100) - }); - } - } - - return stops; - } - - // ----------- - - var FillStyle = pv.FillStyle = function(type) { - this.type = type; - this.key = type; - }; - - /* - * Provide {@link pv.Color} compatibility. - */ - FillStyle.prototype = new pv.Color('none', 1); - - FillStyle.prototype.rgb = function(){ - var color = pv.color(this.color); - if(this.opacity !== color.opacity){ - color = color.alpha(this.opacity); - } - return color; - }; - - /** - * Constructs a solid fill style. This constructor should not be invoked - * directly; use {@link pv.fillStyle} instead. - * - * @class represents a solid fill. - * - * @extends pv.FillStyle - */ - var Solid = pv.FillStyle.Solid = function(color, opacity) { - FillStyle.call(this, 'solid'); - - if(color.rgb){ - this.color = color.color; - this.opacity = color.opacity; - } else { - this.color = color; - this.opacity = opacity; - } - - this.key += " " + this.color + " alpha(" + this.opacity + ")"; - }; - - Solid.prototype = pv.extend(pv.FillStyle); - - Solid.prototype.alpha = function(opacity){ - return new Solid(this.color, opacity); - }; - - Solid.prototype.brighter = function(k){ - return new Solid(this.rgb().brighter(k)); - }; - - Solid.prototype.darker = function(k){ - return new Solid(this.rgb().darker(k)); - }; - - pv.FillStyle.transparent = new Solid(pv.Color.transparent); - - // ---------------- - - var gradient_id = 0; - - var Gradient = pv.FillStyle.Gradient = function(type, stops) { - FillStyle.call(this, type); - - this.id = ++gradient_id; - this.stops = stops; - - if(stops.length){ - // Default color for renderers that do not support gradients - this.color = stops[0].color.color; - } - - this.key += - " stops(" + - stops - .map(function(stop){ - var color = stop.color; - return color.color + " alpha(" + color.opacity + ") at(" + stop.offset + ")"; - }) - .join(", ") + - ")"; - }; - - Gradient.prototype = pv.extend(pv.FillStyle); - - Gradient.prototype.rgb = function(){ - return this.stops.length ? this.stops[0].color : undefined; - }; - - Gradient.prototype.alpha = function(opacity){ - return this._clone(this.stops.map(function(stop){ - return {offset: stop.offset, color: stop.color.alpha(opacity)}; - })); - }; - - Gradient.prototype.darker = function(k){ - return this._clone(this.stops.map(function(stop){ - return {offset: stop.offset, color: stop.color.darker(k)}; - })); - }; - - Gradient.prototype.brighter = function(k){ - return this._clone(this.stops.map(function(stop){ - return {offset: stop.offset, color: stop.color.brighter(k)}; - })); - }; - - // ---------------- - - var LinearGradient = pv.FillStyle.LinearGradient = function(angle, stops) { - Gradient.call(this, 'lineargradient', stops); - - this.angle = angle; - this.key += " angle(" + angle + ")"; - }; - - LinearGradient.prototype = pv.extend(Gradient); - - LinearGradient.prototype._clone = function(stops){ - return new LinearGradient(this.angle, stops); - }; - - // ---------------- - - var RadialGradient = pv.FillStyle.RadialGradient = function(cx, cy, stops) { - Gradient.call(this, 'radialgradient', stops); - - this.cx = cx; - this.cy = cy; - this.key += " center(" + cx + "," + cy + ")"; - }; - - RadialGradient.prototype = pv.extend(Gradient); - - RadialGradient.prototype._clone = function(stops){ - return new RadialGradient(this.cx, this.cy); - }; -})(); -/** - * Returns a linear color ramp from the specified start color to the - * specified end color. The color arguments may be specified either as - * strings or as {@link pv.Color}s. This is equivalent to: - * - *
    pv.Scale.linear().domain(0, 1).range(...)
- * - * @param {string} start the start color; may be a pv.Color. - * @param {string} end the end color; may be a pv.Color. - * @returns {Function} a color ramp from start to end. - * @see pv.Scale.linear - */ -pv.ramp = function(start, end) { - var scale = pv.Scale.linear(); - scale.range.apply(scale, arguments); - return scale; -}; -/** - * @private - * @namespace - */ -pv.Scene = pv.SvgScene = { - /* Various namespaces. */ - svg: "http://www.w3.org/2000/svg", - xmlns: "http://www.w3.org/2000/xmlns", - xlink: "http://www.w3.org/1999/xlink", - xhtml: "http://www.w3.org/1999/xhtml", - - /** The pre-multipled scale, based on any enclosing transforms. */ - scale: 1, - - /** The set of supported events. */ - events: [ - "DOMMouseScroll", // for Firefox - "mousewheel", - "mousedown", - "mouseup", - "mouseover", - "mouseout", - "mousemove", - "click", - "dblclick" - ], - - /** Implicit values for SVG and CSS properties. */ - implicit: { - svg: { - "shape-rendering": "auto", - "pointer-events": "painted", - "x": 0, - "y": 0, - "dy": 0, - "text-anchor": "start", - "transform": "translate(0,0)", - "fill": "none", - "fill-opacity": 1, - "stroke": "none", - "stroke-opacity": 1, - "stroke-width": 1.5, - "stroke-linejoin": "miter", - "stroke-linecap": "butt", - "stroke-miterlimit": 8, - "stroke-dasharray": "none" - }, - css: { - "font": "10px sans-serif" - } - } -}; - -/** - * Updates the display for the specified array of scene nodes. - * - * @param scenes {array} an array of scene nodes. - */ -pv.SvgScene.updateAll = function(scenes) { - if (scenes.length - && scenes[0].reverse - && (scenes.type != "line") - && (scenes.type != "area")) { - var reversed = pv.extend(scenes); - for (var i = 0, j = scenes.length - 1; j >= 0; i++, j--) { - reversed[i] = scenes[j]; - } - scenes = reversed; - } - this.removeSiblings(this[scenes.type](scenes)); -}; - -/** - * Creates a new SVG element of the specified type. - * - * @param type {string} an SVG element type, such as "rect". - * @returns a new SVG element. - */ -pv.SvgScene.create = function(type) { - return document.createElementNS(this.svg, type); -}; - -/** - * Expects the element e to be the specified type. If the element does - * not exist, a new one is created. If the element does exist but is the wrong - * type, it is replaced with the specified element. - * - * @param e the current SVG element. - * @param type {string} an SVG element type, such as "rect". - * @param attributes an optional attribute map. - * @param style an optional style map. - * @returns a new SVG element. - */ -pv.SvgScene.expect = function(e, type, scenes, i, attributes, style) { - var tagName; - if(e){ - tagName = e.tagName; - if(tagName === 'defs'){ - e = e.nextSibling; // may be null - if(e){ - tagName = e.tagName; - } - } else if(tagName === 'a'){ - e = e.firstChild; - // ends up replacing the "a" tag with its child - } - } - - if(e){ - if (tagName !== type) { - var n = this.create(type); - e.parentNode.replaceChild(n, e); - e = n; - } - } else { - e = this.create(type); - } - - if(attributes) this.setAttributes(e, attributes); - if(style) this.setStyle(e, style); - - return e; -}; - -pv.SvgScene.setAttributes = function(e, attributes){ - var implicitSvg = this.implicit.svg; - for (var name in attributes) { - var value = attributes[name]; - if (value == null || value == implicitSvg[name]){ - e.removeAttribute(name); - } else { - e.setAttribute(name, value); - } - } -}; - -pv.SvgScene.setStyle = function(e, style){ - var implicitCss = this.implicit.css; - switch(pv.renderer()){ - case 'batik': - for (var name in style) { - var value = style[name]; - if (value == null || value == implicitCss[name]) { - e.removeAttribute(name); - } else { - e.style.setProperty(name,value); - } - } - break; - - case 'svgweb': - for (var name in style) { - // svgweb doesn't support removeproperty TODO SVGWEB - var value = style[name]; - if (value == null || value == implicitCss[name]) { - continue; - } - e.style[name] = value; - } - break; - - default: - for (var name in style) { - var value = style[name]; - if (value == null || value == implicitCss[name]){ - e.style.removeProperty(name); - } else { - e.style[name] = value; - } - } - } -}; - -/** TODO */ -pv.SvgScene.append = function(e, scenes, index) { - e.$scene = {scenes: scenes, index: index}; - e = this.title(e, scenes[index]); - if (!e.parentNode) scenes.$g.appendChild(e); - return e.nextSibling; -}; - -/** - * Applies a title tooltip to the specified element e, using the - * title property of the specified scene node s. Note that - * this implementation creates both the SVG title element (which - * is the recommended approach, but only works in more modern browsers) and - * the xlink:title attribute which works on more down-level browsers. - * - * @param e an SVG element. - * @param s a scene node. - */ -pv.SvgScene.title = function(e, s) { - var a = e.parentNode; - if (a && (a.tagName != "a")) a = null; - if (s.title) { - if (!a) { - a = this.create("a"); - // for FF>=4 when showing non-title element tooltips - a.setAttributeNS(this.xlink, "xlink:href", ""); - if (e.parentNode) e.parentNode.replaceChild(a, e); - a.appendChild(e); - } - - // Set the title. Using xlink:title ensures the call works in IE - // but only FireFox seems to show the title. - // without xlink: in there, it breaks IE. - a.setAttributeNS(this.xlink, "xlink:title", s.title); // for FF<4 - - // for SVG renderers that follow the recommended approach - var t = null; - for (var c = e.firstChild; c != null; c = c.nextSibling) { - if (c.nodeName == "title") { - t = c; - break; - } - } - if (!t) { - t = this.create("title"); - e.appendChild(t); - } else { - t.removeChild(t.firstChild); // empty out the text - } - - if (pv.renderer() == "svgweb") { // SVGWeb needs an extra 'true' to create SVG text nodes properly in IE. - t.appendChild(document.createTextNode(s.title, true)); - } else { - t.appendChild(document.createTextNode(s.title)); - } - - return a; - } - if (a) a.parentNode.replaceChild(e, a); - return e; -}; - -/** TODO */ -pv.SvgScene.dispatch = pv.listener(function(e) { - var t = e.target.$scene; - if (t) { - var type = e.type; - - /* Fixes for mousewheel support on Firefox & Opera. */ - switch (type) { - case "DOMMouseScroll": - type = "mousewheel"; - e.wheel = -480 * e.detail; - break; - - case "mousewheel": - e.wheel = (window.opera ? 12 : 1) * e.wheelDelta; - break; - } - - if (pv.Mark.dispatch(type, t.scenes, t.index, e)) { - e.preventDefault(); - } - } -}); - -/** @private Remove siblings following element e. */ -pv.SvgScene.removeSiblings = function(e) { - while (e) { - var n = e.nextSibling; - // don't remove a sibling node - if (e.nodeName !== 'defs') { - e.parentNode.removeChild(e); - } - e = n; - } -}; - -/** @private Do nothing when rendering undefined mark types. */ -pv.SvgScene.undefined = function() {}; - -pv.SvgScene.removeFillStyleDefinitions = function(scenes) { - var results = scenes.$g.getElementsByTagName('defs'); - if (results.length === 1) { - var defs; - if (pv.renderer() !== "batik") - defs = results[0]; - else - defs = new cgg.element(results.item(0)); - - var cur = defs.firstChild; - while (cur) { - var next = cur.nextSibling; - if (cur.nodeName == 'linearGradient' || cur.nodeName == 'radialGradient') { - defs.removeChild(cur); - } - cur = next; - } - } -}; - - -(function() { - var dashAliasMap = { - '-': 'shortdash', - '.': 'shortdot', - '-.': 'shortdashdot', - '-..': 'shortdashdotdot', - '. ': 'dot', - '- ': 'dash', - '--': 'longdash', - '- .': 'dashdot', - '--.': 'longdashdot', - '--..': 'longdashdotdot' - }; - - var dashMap = { // SVG specific - values for cap=butt - 'shortdash': [3, 1], - 'shortdot': [1, 1], - 'shortdashdot': [3, 1, 1, 1], - 'shortdashdotdot': [3, 1, 1, 1, 1, 1], - 'dot': [1, 3], - 'dash': [4, 3], - 'longdash': [8, 3], - 'dashdot': [4, 3, 1, 3], - 'longdashdot': [8, 3, 1, 3], - 'longdashdotdot': [8, 3, 1, 3, 1, 3] - }; - - pv.SvgScene.isStandardDashStyle = function(dashArray){ - return dashMap.hasOwnProperty(dashArray); - }; - - pv.SvgScene.translateDashStyleAlias = function(dashArray){ - return dashAliasMap.hasOwnProperty(dashArray) ? - dashAliasMap[dashArray] : - dashArray; - }; - - pv.SvgScene.parseDasharray = function(s){ - // This implementation tries to mimic the VML dashStyle, - // cause the later is more limited... - // - // cap = square and butt result in the same dash pattern - - var dashArray = s.strokeDasharray; - if(dashArray && dashArray !== 'none'){ - dashArray = this.translateDashStyleAlias(dashArray); - - var standardDashArray = dashMap[dashArray]; - if(standardDashArray){ - dashArray = standardDashArray; - } else { - // Make measures relative to line width - dashArray = - dashArray.split(/[\s,]+/); - } - - var lineWidth = s.lineWidth; - var lineCap = s.lineCap || 'butt'; - var isButtCap = lineCap === 'butt'; - - dashArray = - dashArray - .map(function(num, index){ - num = +num; - if(!isButtCap){ - // Steal one unit to dash and give it to the gap, - // to compensate for the round/square cap - if(index % 2){ - // gap - num++; - } else { - // dash/dot - num -= 1; - } - } - - if(num <= 0){ - num = .001; // SVG does not support 0-width; with cap=square/round is useful. - } - - return num * lineWidth / this.scale; - }, this) - .join(' '); - } else { - dashArray = null; - } - - return dashArray; - }; -})(); - -(function() { - - var gradient_definition_id = 0; - - function zeroRounding(x){ - return Math.abs(x) <= 1e-12 ? 0 : x; - } - - pv.SvgScene.addFillStyleDefinition = function(scenes, fill) { - if(!fill.type || fill.type === 'solid'){ - return; - } - - var isLinear = fill.type === 'lineargradient'; - if (isLinear || fill.type === 'radialgradient') { - - var g = scenes.$g; - var results = g.getElementsByTagName('defs'); - var defs; - if(results.length) { - if (pv.renderer() !== "batik") - defs = results.item(0); - else - defs = new cgg.element(results.item(0)); - } else { - defs = g.appendChild(this.create("defs")); - } - - var elem; - var className = '__pv_gradient' + fill.id; - - // TODO: check this check exists method. It looks wrong... - //1107[PVALE] - No ideia what this was supposed to do, but the method querySelector does not seem to exist - results = undefined; //defs.querySelector('.' + className); - if (!results) { - var instId = '__pv_gradient' + fill.id + '_inst_' + (++gradient_definition_id); - - elem = defs.appendChild(this.create(isLinear ? "linearGradient" : "radialGradient")); - elem.setAttribute("id", instId); - elem.setAttribute("class", className); - // Use the default: objectBoundingBox units - // Coordinates are %s of the width and height of the BBox - // 0,0 = top, left - // 1,1 = bottom, right - -// elem.setAttribute("gradientUnits","userSpaceOnUse"); - - if(isLinear){ - // x1,y1 -> x2,y2 form the gradient vector - // See http://www.w3.org/TR/css3-images/#gradients example 11 on calculating the gradient line - // Gradient-Top angle -> SVG angle -> From diagonal angle - // angle = (gradAngle - 90) - 45 = angle - 135 - var svgAngle = fill.angle - Math.PI/2; - var diagAngle = Math.abs(svgAngle % (Math.PI/2)) - Math.PI/4; - - // Radius from the center of the normalized bounding box - var radius = Math.abs((Math.SQRT2/2) * Math.cos(diagAngle)); - - var dirx = radius * Math.cos(svgAngle); - var diry = radius * Math.sin(svgAngle); - - var x1 = zeroRounding(0.5 - dirx); - var y1 = zeroRounding(0.5 - diry); - var x2 = zeroRounding(0.5 + dirx); - var y2 = zeroRounding(0.5 + diry); - - elem.setAttribute("x1", x1); - elem.setAttribute("y1", y1); - elem.setAttribute("x2", x2); - elem.setAttribute("y2", y2); - } else { - // Currently using defaults cx = cy = r = 0.5 - -// elem.setAttribute("cx", fill.cx); -// elem.setAttribute("cy", fill.cy); -// elem.setAttribute("r", fill.r ); - } - - var stops = fill.stops; - for (var i = 0, S = stops.length; i < S ; i++) { - var stop = stops[i]; - var stopElem = elem.appendChild(this.create("stop")); - var color = stop.color; - stopElem.setAttribute("offset", stop.offset + '%' ); - stopElem.setAttribute("stop-color", color.color ); - stopElem.setAttribute("stop-opacity", color.opacity + ''); - } - - fill.color = 'url(#' + instId + ')'; - } - } - }; - -})(); -/** - * @private Converts the specified b-spline curve segment to a bezier curve - * compatible with SVG "C". - * - * @param p0 the first control point. - * @param p1 the second control point. - * @param p2 the third control point. - * @param p3 the fourth control point. - */ -pv.SvgScene.pathBasis = (function() { - - /** - * Matrix to transform basis (b-spline) control points to bezier control - * points. Derived from FvD 11.2.8. - */ - var basis = [ - [ 1/6, 2/3, 1/6, 0 ], - [ 0, 2/3, 1/3, 0 ], - [ 0, 1/3, 2/3, 0 ], - [ 0, 1/6, 2/3, 1/6 ] - ]; - - /** - * Returns the point that is the weighted sum of the specified control points, - * using the specified weights. This method requires that there are four - * weights and four control points. - */ - function weight(w, p0, p1, p2, p3) { - return { - x: w[0] * p0.left + w[1] * p1.left + w[2] * p2.left + w[3] * p3.left, - y: w[0] * p0.top + w[1] * p1.top + w[2] * p2.top + w[3] * p3.top - }; - } - - var convert = function(p0, p1, p2, p3) { - var b1 = weight(basis[1], p0, p1, p2, p3), - b2 = weight(basis[2], p0, p1, p2, p3), - b3 = weight(basis[3], p0, p1, p2, p3); - return "C" + b1.x + "," + b1.y - + "," + b2.x + "," + b2.y - + "," + b3.x + "," + b3.y; - }; - - convert.segment = function(p0, p1, p2, p3) { - var b0 = weight(basis[0], p0, p1, p2, p3), - b1 = weight(basis[1], p0, p1, p2, p3), - b2 = weight(basis[2], p0, p1, p2, p3), - b3 = weight(basis[3], p0, p1, p2, p3); - return ["M" + b0.x + "," + b0.y, - "C" + b1.x + "," + b1.y + "," + - b2.x + "," + b2.y + "," + - b3.x + "," + b3.y]; - }; - - return convert; -})(); - -/** - * @private Interpolates the given points using the basis spline interpolation. - * Returns an SVG path without the leading M instruction to allow path - * appending. - * - * @param points the array of points. - */ -pv.SvgScene.curveBasis = function(points, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - if (L <= 2) return ""; - - var path = "", - p0 = points[from], - p1 = p0, - p2 = p0, - p3 = points[from + 1]; - path += this.pathBasis(p0, p1, p2, p3); - for (var i = from + 2 ; i <= to ; i++) { - p0 = p1; - p1 = p2; - p2 = p3; - p3 = points[i]; - path += this.pathBasis(p0, p1, p2, p3); - } - /* Cycle through to get the last point. */ - path += this.pathBasis(p1, p2, p3, p3); - path += this.pathBasis(p2, p3, p3, p3); - return path; -}; - -/** - * @private Interpolates the given points using the basis spline interpolation. - * If points.length == tangents.length then a regular Hermite interpolation is - * performed, if points.length == tangents.length + 2 then the first and last - * segments are filled in with cubic bazier segments. Returns an array of path - * strings. - * - * @param points the array of points. - */ -pv.SvgScene.curveBasisSegments = function(points, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - if (L <= 2) return ""; // BUG? - - var paths = [], - p0 = points[from], - p1 = p0, - p2 = p0, - p3 = points[from + 1], - firstPath = this.pathBasis.segment(p0, p1, p2, p3); - - p0 = p1; - p1 = p2; - p2 = p3; - p3 = points[from + 2]; - firstPath[1] += this.pathBasis(p0, p1, p2, p3); // merge first & second path - paths.push(firstPath); - - for (var i = from + 3; i <= to ; i++) { - p0 = p1; - p1 = p2; - p2 = p3; - p3 = points[i]; - paths.push(this.pathBasis.segment(p0, p1, p2, p3)); - } - - // merge last & second-to-last path - var lastPath = this.pathBasis.segment(p1, p2, p3, p3); - lastPath[1] += this.pathBasis(p2, p3, p3, p3); - paths.push(lastPath); - - return paths; -}; - -/** - * @private Interpolates the given points with respective tangents using the cubic - * Hermite spline interpolation. If points.length == tangents.length then a regular - * Hermite interpolation is performed, if points.length == tangents.length + 2 then - * the first and last segments are filled in with cubic bezier segments. - * Returns an SVG path without the leading M instruction to allow path appending. - * - * @param points the array of points. - * @param tangents the array of tangent vectors. - */ -pv.SvgScene.curveHermite = function(points, tangents, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - var T = tangents.length; - if (T < 1 || (L !== T && L !== T + 2)) { - return ""; - } - - var quad = L !== T, - path = "", - p0 = points[from], - p = points[from + 1], - t0 = tangents[0], - t = t0, - pi = from + 1; - - if (quad) { - path += "Q" + - (p.left - t0.x * 2 / 3) + "," + (p.top - t0.y * 2 / 3) + "," + - p.left + "," + p.top; - p0 = points[from + 1]; - pi = from + 2; - } - - if (T > 1) { - t = tangents[1]; - p = points[pi]; - pi++; - path += "C" + - (p0.left + t0.x) + "," + (p0.top + t0.y) + "," + - (p.left - t.x) + "," + (p.top - t.y) + "," + - p.left + "," + p.top; - - for (var i = 2 ; i < T ; i++, pi++) { - p = points[pi]; - t = tangents[i]; - path += "S" + - (p.left - t.x) + "," + (p.top - t.y) + "," + - p.left + "," + p.top; - } - } - - if (quad) { - var lp = points[pi]; - path += "Q" + - (p.left + t.x * 2 / 3) + "," + (p.top + t.y * 2 / 3) + "," + - lp.left + "," + lp.top; - } - - return path; -}; - -/** - * @private Interpolates the given points with respective tangents using the - * cubic Hermite spline interpolation. Returns an array of path strings. - * - * @param points the array of points. - * @param tangents the array of tangent vectors. - */ -pv.SvgScene.curveHermiteSegments = function(points, tangents, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - var T = tangents.length; - if (T < 1 || (L !== T && L !== T + 2)) { - return []; - } - - var quad = L !== T, - paths = [], - p0 = points[from], - p = p0, - t0 = tangents[0], - t = t0, - pi = from + 1; - - if (quad) { - p = points[from + 1]; - paths.push(["M" + p0.left + "," + p0.top, - "Q" + (p.left - t.x * 2 / 3) + "," + - (p.top - t.y * 2 / 3) + "," + - p.left + "," + p.top]); - pi = from + 2; - } - - for (var i = 1; i < T; i++, pi++) { - p0 = p; - t0 = t; - p = points[pi]; - t = tangents[i]; - paths.push(["M" + p0.left + "," + p0.top, - "C" + (p0.left + t0.x) + "," + (p0.top + t0.y) + "," + - (p.left - t.x ) + "," + (p.top - t.y) + "," + - p.left + "," + p.top]); - } - - if (quad) { - var lp = points[pi]; - paths.push(["M" + p.left + "," + p.top, - "Q" + (p.left + t.x * 2 / 3) + "," + (p.top + t.y * 2 / 3) + "," + - lp.left + "," + lp.top]); - } - - return paths; -}; - -/** - * @private Computes the tangents for the given points needed for cardinal - * spline interpolation. Returns an array of tangent vectors. Note: that for n - * points only the n-2 well defined tangents are returned. - * - * @param points the array of points. - * @param tension the tension of hte cardinal spline. - */ -pv.SvgScene.cardinalTangents = function(points, tension, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - var tangents = [], - a = (1 - tension) / 2, - p0 = points[from], - p1 = points[from + 1], - p2 = points[from + 2]; - - for (var i = from + 3 ; i <= to ; i++) { - tangents.push({x: a * (p2.left - p0.left), y: a * (p2.top - p0.top)}); - p0 = p1; - p1 = p2; - p2 = points[i]; - } - - tangents.push({x: a * (p2.left - p0.left), y: a * (p2.top - p0.top)}); - - return tangents; -}; - -/** - * @private Interpolates the given points using cardinal spline interpolation. - * Returns an SVG path without the leading M instruction to allow path - * appending. - * - * @param points the array of points. - * @param tension the tension of the cardinal spline. - */ -pv.SvgScene.curveCardinal = function(points, tension, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - if (L <= 2) return ""; - return this.curveHermite(points, this.cardinalTangents(points, tension, from, to), from, to); -}; - -/** - * @private Interpolates the given points using cardinal spline interpolation. - * Returns an array of path strings. - * - * @param points the array of points. - * @param tension the tension of the cardinal spline. - */ -pv.SvgScene.curveCardinalSegments = function(points, tension, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - if (L <= 2) return ""; // BUG? - return this.curveHermiteSegments(points, this.cardinalTangents(points, tension, from, to), from, to); -}; - -/** - * @private Interpolates the given points using Fritsch-Carlson Monotone cubic - * Hermite interpolation. Returns an array of tangent vectors. - * - * @param points the array of points. - */ -pv.SvgScene.monotoneTangents = function(points, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - var tangents = [], - d = [], - m = [], - dx = [], - k = 0, - j; - - /* Compute the slopes of the secant lines between successive points. */ - for (k = 0 ; k < L - 1 ; k++) { - j = from + k; - var den = points[j+1].left - points[j].left; - d[k] = Math.abs(den) <= 1e-12 ? 0 : (points[j+1].top - points[j].top)/den; - } - - /* Initialize the tangents at every point as the average of the secants. */ - m[0] = d[0]; - dx[0] = points[from + 1].left - points[from].left; - for (k = 1, j = from + k ; k < L - 1 ; k++, j++) { - m[k] = (d[k-1]+d[k])/2; - dx[k] = (points[j+1].left - points[j-1].left)/2; - } - m[k] = d[k-1]; - dx[k] = (points[j].left - points[j-1].left); - - /* Step 3. Very important, step 3. Yep. Wouldn't miss it. */ - for (k = 0; k < L - 1; k++) { - if (d[k] == 0) { - m[ k ] = 0; - m[k+1] = 0; - } - } - - /* Step 4 + 5. Out of 5 or more steps. */ - for (k = 0; k < L - 1; k++) { - if ((Math.abs(m[k]) < 1e-5) || (Math.abs(m[k+1]) < 1e-5)) continue; - var ak = m[k] / d[k], - bk = m[k + 1] / d[k], - s = ak * ak + bk * bk; // monotone constant (?) - if (s > 9) { - var tk = 3 / Math.sqrt(s); - m[k] = tk * ak * d[k]; - m[k + 1] = tk * bk * d[k]; - } - } - - var len; - for (var i = 0 ; i < L ; i++) { - len = 1 + m[i] * m[i]; // pv.vector(1, m[i]).norm().times(dx[i]/3) - tangents.push({x: dx[i] / 3 / len, y: m[i] * dx[i] / 3 / len}); - } - - return tangents; -}; - -/** - * @private Interpolates the given points using Fritsch-Carlson Monotone cubic - * Hermite interpolation. Returns an SVG path without the leading M instruction - * to allow path appending. - * - * @param points the array of points. - */ -pv.SvgScene.curveMonotone = function(points, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - if (L <= 2) return ""; - return this.curveHermite(points, this.monotoneTangents(points, from, to), from, to); -}; - -/** - * @private Interpolates the given points using Fritsch-Carlson Monotone cubic - * Hermite interpolation. - * Returns an array of path strings. - * - * @param points the array of points. - */ -pv.SvgScene.curveMonotoneSegments = function(points, from, to) { - var L; - if(from == null){ - L = points.length; - from = 0; - to = L -1; - } else { - L = to - from + 1; - } - - if (L <= 2) return ""; // BUG? - return this.curveHermiteSegments(points, this.monotoneTangents(points, from, to), from, to); -}; -pv.SvgScene.area = function(scenes) { - var e = scenes.$g.firstChild; - - this.removeFillStyleDefinitions(scenes); - - var count = scenes.length; - if (!count){ - return e; - } - - var s = scenes[0]; - - /* smart segmentation */ - if (s.segmented === 'smart') { - return this.areaSegmentedSmart(e, scenes); - } - - /* full segmented */ - if (s.segmented) { - return this.areaSegmentedFull(e, scenes); - } - - return this.areaFixed(e, scenes, 0, count - 1, /*addEvents*/ true); -}; - -pv.SvgScene.areaFixed = function(elm, scenes, from, to, addEvents) { - var count = to - from + 1; - - // count > 0 - - if(count === 1){ - return this.lineAreaDot(elm, scenes, from); - } - - var s = scenes[from]; - if (!s.visible) { - return elm; - } - - /* fill & stroke */ - - var fill = s.fillStyle; - var stroke = s.strokeStyle; - - if (!fill.opacity && !stroke.opacity) { - return elm; - } - - this.addFillStyleDefinition(scenes, fill); - this.addFillStyleDefinition(scenes, stroke); - - var isInterpBasis = false; - var isInterpCardinal = false; - var isInterpMonotone = false; - var isInterpStepAfter = false; - var isInterpStepBefore = false; - switch(s.interpolate){ - case 'basis': isInterpBasis = true; break; - case 'cardinal': isInterpCardinal = true; break; - case 'monotone': isInterpMonotone = true; break; - case 'step-after': isInterpStepAfter = true; break; - case 'step-before': isInterpStepBefore = true; break; - } - - var isInterpBasisCardinalOrMonotone = isInterpBasis || isInterpCardinal || isInterpMonotone; - - /* points */ - var d = [], si, sj; - for (var i = from ; i <= to ; i++) { - si = scenes[i]; - if (!si.width && !si.height) { - continue; - } - - for (var j = i + 1; j <= to ; j++) { - sj = scenes[j]; - if (!sj.width && !sj.height) { - break; - } - } - - if ((i > from) && !isInterpStepAfter){ - i--; - } - - if ((j <= to) && !isInterpStepBefore) { - j++; - } - - var fun = isInterpBasisCardinalOrMonotone && (j - i > 2) ? - this.areaPathCurve : - this.areaPathStraight; - - d.push( fun.call(this, scenes, i, j - 1, s) ); - i = j - 1; - } - - if (!d.length) { - return elm; - } - - var sop = stroke.opacity; - elm = this.expect(elm, "path", scenes, from, { - "shape-rendering": s.antialias ? null : "crispEdges", - "pointer-events": addEvents ? s.events : 'none', - "cursor": s.cursor, - "d": "M" + d.join("ZM") + "Z", - "fill": fill.color, - "fill-opacity": fill.opacity || null, - "stroke": stroke.color, - "stroke-opacity": sop || null, - "stroke-width": sop ? (s.lineWidth / this.scale) : null, - "stroke-linecap": s.lineCap, - "stroke-linejoin": s.lineJoin, - "stroke-miterlimit": s.strokeMiterLimit, - "stroke-dasharray": sop ? this.parseDasharray(s) : null - }); - - if(s.svg) this.setAttributes(elm, s.svg); - if(s.css) this.setStyle(elm, s.css); - - return this.append(elm, scenes, from); -}; - -pv.SvgScene.areaSegmentedSmart = function(elm, scenes) { - - var eventsSegments = scenes.mark.$hasHandlers ? [] : null; - - /* Visual only */ - // Iterate *visible* scene segments - elm = this.eachLineAreaSegment(elm, scenes, function(elm, scenes, from, to){ - - // Paths depend only on visibility - var segment = this.areaSegmentPaths(scenes, from, to); - var pathsT = segment.top; - var pathsB = segment.bottom; - var fromp = from; - - // Events segments also, depend only on visibility - if(eventsSegments){ - eventsSegments.push(segment); - } - - // Split this visual scenes segment, - // on key properties changes - var options = { - breakOnKeyChange: true, - from: from, - to: to - }; - - return this.eachLineAreaSegment(elm, scenes, options, function(elm, scenes, from, to){ - - var s1 = scenes[from]; - - var fill = s1.fillStyle; - var stroke = s1.strokeStyle; - - this.addFillStyleDefinition(scenes, fill); - this.addFillStyleDefinition(scenes, stroke); - - if(from === to){ - // Visual and events - return this.lineAreaDotAlone(elm, scenes, from); - } - - var d = this.areaJoinPaths(pathsT, pathsB, from - fromp, to - fromp - 1); // N - 1 paths connect N points - - var sop = stroke.opacity; - var attrs = { - 'shape-rendering': s1.antialias ? null : 'crispEdges', - 'pointer-events': 'none', - 'cursor': s1.cursor, - 'd': d, - 'fill': fill.color, - 'fill-opacity': fill.opacity || null, - 'stroke': stroke.color, - 'stroke-opacity': sop || null, - 'stroke-width': sop ? (s1.lineWidth / this.scale) : null, - 'stroke-linecap': s1.lineCap, - 'stroke-linejoin': s1.lineJoin, - 'stroke-miterlimit': s1.strokeMiterLimit, - 'stroke-dasharray': sop ? this.parseDasharray(s1) : null - }; - - elm = this.expect(elm, 'path', scenes, from, attrs, s1.css); - - return this.append(elm, scenes, from); - }); - }); - - /* Events */ - if(eventsSegments){ - eventsSegments.forEach(function(segment){ - var from = segment.from; - var pathsT = segment.top; - var pathsB = segment.bottom; - var P = pathsT.length; - - var attrsBase = { - 'shape-rendering': 'crispEdges', - 'fill': 'rgb(127,127,127)', - 'fill-opacity': 0.005, // VML requires this much to fire events - 'stroke': null - }; - - pathsT.forEach(function(pathT, j){ - var i = from + j; - var s = scenes[i]; - - var events = s.events; - if(events && events !== "none"){ - var pathB = pathsB[P - j - 1]; - - var attrs = Object.create(attrsBase); - attrs['pointer-events'] = events; - attrs.cursor = s.cursor; - attrs.d = pathT.join("") + "L" + pathB[0].substr(1) + pathB[1] + "Z"; - - elm = this.expect(elm, 'path', scenes, i, attrs); - - elm = this.append(elm, scenes, i); - } - }, this); - }, this); - } - - return elm; -}; - -pv.SvgScene.areaSegmentPaths = function(scenes, from, to) { - return this.areaSegmentCurvePaths (scenes, from, to) || - this.areaSegmentStraightPaths(scenes, from, to); -}; - -pv.SvgScene.areaSegmentCurvePaths = function(scenes, from, to){ - var count = to - from + 1; - - // count > 0 - - var s = scenes[from]; - - // Interpolated paths for scenes 0 to count-1 - var isBasis = s.interpolate === "basis"; - var isCardinal = !isBasis && s.interpolate === "cardinal"; - if (isBasis || isCardinal || s.interpolate == "monotone") { - var pointsT = []; - var pointsB = []; - for (var i = 0 ; i < count ; i++) { - var si = scenes[from + i]; // from -> to - var sj = scenes[to - i]; // to -> from - - pointsT.push(si); - pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height}); - } - - var pathsT, pathsB; - if (isBasis) { - pathsT = this.curveBasisSegments(pointsT); - pathsB = this.curveBasisSegments(pointsB); - } else if (isCardinal) { - pathsT = this.curveCardinalSegments(pointsT, s.tension); - pathsB = this.curveCardinalSegments(pointsB, s.tension); - } else { // monotone - pathsT = this.curveMonotoneSegments(pointsT); - pathsB = this.curveMonotoneSegments(pointsB); - } - - if(pathsT || pathsT.length){ - return { - from: from, - top: pathsT, - bottom: pathsB - }; - } - } -}; - -/** @private Computes the straight path for the range [i, j]. */ -pv.SvgScene.areaSegmentStraightPaths = function(scenes, i, j){ - var pathsT = []; - var pathsB = []; - - for (var k = j, m = i ; i < k ; i++, j--) { - // i - top line index, from i to j - // j - bottom line index, from j to i - var si = scenes[i], - sj = scenes[j], - pi = ['M' + si.left + "," + si.top], - pj = ['M' + (sj.left + sj.width) + "," + (sj.top + sj.height)]; - - /* interpolate */ - var sk = scenes[i + 1], // top line - sl = scenes[j - 1]; // bottom line - switch(si.interpolate){ - case 'step-before': - pi.push("V" + sk.top + "H" + sk.left); - //pj.push("H" + (sl.left + sl.width)); - break; - - case 'step-after': - pi.push("H" + sk.left + "V" + sk.top); - //pj.push("V" + (sl.top + sl.height)); - break; - - default: // linear - pi.push("L" + sk.left + "," + sk.top); - } - - pj.push("L" + (sl.left + sl.width) + "," + (sl.top + sl.height)); - - pathsT.push(pi); - pathsB.push(pj); - } - - return { - from: m, - top: pathsT, - bottom: pathsB - }; -}; - -pv.SvgScene.areaJoinPaths = function(pathsT, pathsB, i, j){ - /* - * Scenes -> 0 ... N-1 - * pathsT -> 0 1 2 3 4 5 6 7 8 9 - * 9 8 7 6 5 4 3 2 1 0 <- pathsB - * | | - * i<->j - * - */ - var fullPathT = ""; - var fullPathB = ""; - - var N = pathsT.length; - - for (var k = i, l = N - 1 - j ; k <= j ; k++, l++) { - var pathT = pathsT[k]; - var pathB = pathsB[l]; - - var dT; - var dB; - if(k === i){ - // Add moveTo and lineTo of first (top) part - dT = pathT.join(""); - - // Join top and bottom parts with a line to the bottom right point - dB = "L" + pathB[0].substr(1) + pathB[1]; - } else { - // Add lineTo only, on following parts - dT = pathT[1]; - dB = pathB[1]; - } - - fullPathT += dT; - fullPathB += dB; - } - - // Close the path with Z - return fullPathT + fullPathB + "Z"; -}; - -pv.SvgScene.areaSegmentedFull = function(e, scenes) { - // Curve interpolations paths for each scene - var count = scenes.length; - - var pathsT, pathsB; - var result = this.areaSegmentCurvePaths(scenes, 0, count - 1); - if(result){ - pathsT = result.top; - pathsB = result.bottom; - } - - // ------------- - - var s = scenes[0]; - for (var i = 0 ; i < count - 1 ; i++) { - var s1 = scenes[i]; - var s2 = scenes[i + 1]; - - /* visible */ - if (!s1.visible || !s2.visible) { - continue; - } - - var fill = s1.fillStyle; - var stroke = s1.strokeStyle; - if (!fill.opacity && !stroke.opacity) { - continue; - } - - var d; - if (pathsT) { - var pathT = pathsT[i].join(""), - pathB = "L" + pathsB[count - i - 2].join("").substr(1); - - d = pathT + pathB + "Z"; - } else { - /* interpolate */ - var si = s1; - var sj = s2; - switch (s1.interpolate) { - case "step-before": si = s2; break; - case "step-after": sj = s1; break; - } - - /* path */ - d = "M" + s1.left + "," + si.top - + "L" + s2.left + "," + sj.top - + "L" + (s2.left + s2.width) + "," + (sj.top + sj.height) - + "L" + (s1.left + s1.width) + "," + (si.top + si.height) - + "Z"; - } - - var attrs = { - "shape-rendering": s1.antialias ? null : "crispEdges", - "pointer-events": s1.events, - "cursor": s1.cursor, - "d": d, - "fill": fill.color, - "fill-opacity": fill.opacity || null, - "stroke": stroke.color, - "stroke-opacity": stroke.opacity || null, - "stroke-width": stroke.opacity ? s1.lineWidth / this.scale : null - }; - - e = this.expect(e, "path", scenes, i, attrs); - - if(s1.svg) this.setAttributes(e, s1.svg); - if(s1.css) this.setStyle(e, s1.css); - - e = this.append(e, scenes, i); - } - return e; -}; - - -/** @private Computes the straight path for the range [i, j]. */ -pv.SvgScene.areaPathStraight = function(scenes, i, j, s){ - var pointsT = []; - var pointsB = []; - - for (var k = j ; i <= k ; i++, j--) { - // i - top line index, from i to j - // j - bottom line index, from j to i - var si = scenes[i], - sj = scenes[j], - pi = si.left + "," + si.top, - pj = (sj.left + sj.width) + "," + (sj.top + sj.height); - - /* interpolate */ - if (i < k) { - var sk = scenes[i + 1], // top line - sl = scenes[j - 1]; // bottom line - switch(s.interpolate){ - case 'step-before': - pi += "V" + sk.top; - pj += "H" + (sl.left + sl.width); - break; - case 'step-after': - pi += "H" + sk.left; - pj += "V" + (sl.top + sl.height); - break; - } - } - - pointsT.push(pi); - pointsB.push(pj); - } - - return pointsT.concat(pointsB).join("L"); -}; - -/** @private Computes the curved path for the range [i, j]. */ -pv.SvgScene.areaPathCurve = function(scenes, i, j, s){ - var pointsT = []; - var pointsB = []; - var pathT, pathB; - - for (var k = j; i <= k; i++, j--) { - var sj = scenes[j]; - pointsT.push(scenes[i]); - pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height}); - } - - switch(s.interpolate){ - case 'basis': - pathT = this.curveBasis(pointsT); - pathB = this.curveBasis(pointsB); - break; - - case 'cardinal': - pathT = this.curveCardinal(pointsT, s.tension); - pathB = this.curveCardinal(pointsB, s.tension); - break; - - default: // monotone - pathT = this.curveMonotone(pointsT); - pathB = this.curveMonotone(pointsB); - } - - return pointsT[0].left + "," + pointsT[0].top + - pathT + - "L" + - pointsB[0].left + "," + pointsB[0].top + - pathB; -}; -pv.SvgScene.minBarWidth = 1; -pv.SvgScene.minBarHeight = 1; -pv.SvgScene.minBarLineWidth = 0.2; - -pv.SvgScene.bar = function(scenes) { - var e = scenes.$g.firstChild; - - this.removeFillStyleDefinitions(scenes); - - for (var i = 0; i < scenes.length; i++) { - var s = scenes[i]; - - /* visible */ - if (!s.visible || Math.abs(s.width) <= 1E-10 || Math.abs(s.height) <= 1E-10) continue; - if(s.width < this.minBarWidth){ - s.width = this.minBarWidth; - } - - if(s.height < this.minBarHeight){ - s.height = this.minBarHeight; - } - - var fill = s.fillStyle, stroke = s.strokeStyle; - if (!fill.opacity && !stroke.opacity) continue; - - if (fill.type && fill.type !== 'solid') { - this.addFillStyleDefinition(scenes,fill); - } - - if (stroke.type && stroke.type != 'solid') { - this.addFillStyleDefinition(scenes,stroke); - } - - var lineWidth; - if(stroke.opacity){ - lineWidth = s.lineWidth; - if(lineWidth < 1e-10){ - lineWidth = 0; - } else { - lineWidth = Math.max(this.minBarLineWidth, lineWidth / this.scale); - } - } else { - lineWidth = null; - } - - e = this.expect(e, "rect", scenes, i, { - "shape-rendering": s.antialias ? null : "crispEdges", - "pointer-events": s.events, - "cursor": s.cursor, - "x": s.left, - "y": s.top, - "width": Math.max(1E-10, s.width), - "height": Math.max(1E-10, s.height), - "fill": fill.color, - "fill-opacity": fill.opacity || null, - "stroke": stroke.color, - "stroke-opacity": stroke.opacity || null, - "stroke-width": lineWidth, - "stroke-linecap": s.lineCap, - "stroke-dasharray": stroke.opacity ? this.parseDasharray(s) : null - }); - - if(s.svg) this.setAttributes(e, s.svg); - if(s.css) this.setStyle(e, s.css); - - e = this.append(e, scenes, i); - } - return e; -}; -pv.SvgScene.dot = function(scenes) { - var e = scenes.$g.firstChild; - - this.removeFillStyleDefinitions(scenes); - - for (var i = 0; i < scenes.length; i++) { - var s = scenes[i]; - - /* visible */ - if (!s.visible) continue; - var fill = s.fillStyle, stroke = s.strokeStyle; - if (!fill.opacity && !stroke.opacity) continue; - - if (fill.type && fill.type !== 'solid') { - this.addFillStyleDefinition(scenes,fill); - } - - if (stroke.type && stroke.type != 'solid') { - this.addFillStyleDefinition(scenes,stroke); - } - - /* points */ - var radius = s.shapeRadius, path = null; - switch (s.shape) { - case "cross": { - path = "M" + -radius + "," + -radius - + "L" + radius + "," + radius - + "M" + radius + "," + -radius - + "L" + -radius + "," + radius; - break; - } - case "triangle": { - var h = radius, w = radius * 1.1547; // 2 / Math.sqrt(3) - path = "M0," + h - + "L" + w +"," + -h - + " " + -w + "," + -h - + "Z"; - break; - } - case "diamond": { - radius *= Math.SQRT2; - path = "M0," + -radius - + "L" + radius + ",0" - + " 0," + radius - + " " + -radius + ",0" - + "Z"; - break; - } - case "square": { - path = "M" + -radius + "," + -radius - + "L" + radius + "," + -radius - + " " + radius + "," + radius - + " " + -radius + "," + radius - + "Z"; - break; - } - case "tick": { - path = "M0,0L0," + -s.shapeSize; - break; - } - case "bar": { - path = "M0," + (s.shapeSize / 2) + "L0," + -(s.shapeSize / 2); - break; - } - } - - /* Use for circles, for everything else. */ - var svg = { - "shape-rendering": s.antialias ? null : "crispEdges", - "pointer-events": s.events, - "cursor": s.cursor, - "fill": fill.color, - "fill-opacity": fill.opacity || null, - "stroke": stroke.color, - "stroke-opacity": stroke.opacity || null, - "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null, - "stroke-linecap": s.lineCap, - "stroke-dasharray": stroke.opacity ? this.parseDasharray(s) : null - }; - if (path) { - svg.transform = "translate(" + s.left + "," + s.top + ")"; - if (s.shapeAngle) svg.transform += " rotate(" + 180 * s.shapeAngle / Math.PI + ")"; - svg.d = path; - e = this.expect(e, "path", scenes, i, svg); - } else { - svg.cx = s.left; - svg.cy = s.top; - svg.r = radius; - e = this.expect(e, "circle", scenes, i, svg); - } - - if(s.svg) this.setAttributes(e, s.svg); - if(s.css) this.setStyle(e, s.css); - - e = this.append(e, scenes, i); - } - return e; -}; -pv.SvgScene.image = function(scenes) { - var e = scenes.$g.firstChild; - for (var i = 0; i < scenes.length; i++) { - var s = scenes[i]; - - /* visible */ - if (!s.visible) continue; - - /* fill */ - e = this.fill(e, scenes, i); - - /* image */ - if (s.image) { - e = this.expect(e, "foreignObject", scenes, i, { - "cursor": s.cursor, - "x": s.left, - "y": s.top, - "width": s.width, - "height": s.height - }); - if(s.svg) this.setAttributes(e, s.svg); - if(s.css) this.setStyle(e, s.css); - var c = e.firstChild || e.appendChild(document.createElementNS(this.xhtml, "canvas")); - c.$scene = {scenes:scenes, index:i}; - c.style.width = s.width; - c.style.height = s.height; - c.width = s.imageWidth; - c.height = s.imageHeight; - c.getContext("2d").putImageData(s.image, 0, 0); - } else { - e = this.expect(e, "image", scenes, i, { - "preserveAspectRatio": "none", - "cursor": s.cursor, - "x": s.left, - "y": s.top, - "width": s.width, - "height": s.height - }); - - if(s.svg) this.setAttributes(e, s.svg); - if(s.css) this.setStyle(e, s.css); - - e.setAttributeNS(this.xlink, "xlink:href", s.url); - } - e = this.append(e, scenes, i); - - /* stroke */ - e = this.stroke(e, scenes, i); - } - return e; -}; -pv.SvgScene.label = function(scenes) { - var e = scenes.$g.firstChild; - for (var i = 0; i < scenes.length; i++) { - var s = scenes[i]; - - /* visible */ - if (!s.visible) continue; - var fill = s.textStyle; - if (!fill.opacity || !s.text) continue; - - /* text-baseline, text-align */ - var x = 0, y = 0, dy = 0, anchor = "start"; - switch (s.textBaseline) { - case "middle": - if (pv.renderer() == 'svgweb') - y = 3; // flex doesn't seem to use dy, so this moves it to be 'about right' - else - dy = ".35em"; - break; - case "top": - if (pv.renderer() == 'svgweb') { - y = 9 + s.textMargin; // flex doesn't seem to use dy, so this moves it to be 'about right' - } else { - dy = ".71em"; y = s.textMargin; - } - break; - case "bottom": y = "-" + s.textMargin; break; - } - switch (s.textAlign) { - case "right": anchor = "end"; x = "-" + s.textMargin; break; - case "center": anchor = "middle"; break; - case "left": x = s.textMargin; break; - } - - e = this.expect(e, "text", scenes, i, { - "pointer-events": s.events, - "cursor": s.cursor, - "x": x, - "y": y, - "dy": dy, - "transform": "translate(" + s.left + "," + s.top + ")" - + (s.textAngle ? " rotate(" + 180 * s.textAngle / Math.PI + ")" : "") - + (this.scale != 1 ? " scale(" + 1 / this.scale + ")" : ""), - "fill": fill.color, - "fill-opacity": fill.opacity || null, - "text-anchor": anchor - }, { - "font": s.font, - "text-shadow": s.textShadow, - "text-decoration": s.textDecoration - }); - - if(s.svg) this.setAttributes(e, s.svg); - if(s.css) this.setStyle(e, s.css); - - if (e.firstChild) e.firstChild.nodeValue = s.text; - else { - if (pv.renderer() == "svgweb") { // SVGWeb needs an extra 'true' to create SVG text nodes properly in IE. - e.appendChild(document.createTextNode(s.text, true)); - } else { - e.appendChild(document.createTextNode(s.text)); - } - } - - e = this.append(e, scenes, i); - } - return e; -}; -pv.SvgScene.line = function(scenes) { - var e = scenes.$g.firstChild; - - this.removeFillStyleDefinitions(scenes); - - var count = scenes.length; - if (!count){ - return e; - } - - var s = scenes[0]; - - /* smart segmentation */ - if (s.segmented === 'smart') { - return this.lineSegmentedSmart(e, scenes); - } - - if (count < 2) { - return e; - } - - /* full segmentation */ - if (s.segmented) { - return this.lineSegmentedFull(e, scenes); - } - - return this.lineFixed(e, scenes); -}; - -pv.SvgScene.lineFixed = function(elm, scenes) { - - var count = scenes.length; - - // count > 0 - - if(count === 1){ - return this.lineAreaDotAlone(elm, scenes, 0); - } - - var s = scenes[0]; - if (!s.visible) { - return elm; - } - - /* fill & stroke */ - - var fill = s.fillStyle; - var stroke = s.strokeStyle; - - if (!fill.opacity && !stroke.opacity) { - return elm; - } - - this.addFillStyleDefinition(scenes, fill); - this.addFillStyleDefinition(scenes, stroke); - - /* points */ - var d = "M" + s.left + "," + s.top; - - var curveInterpolated = (count > 2); - if(curveInterpolated) { - switch(s.interpolate) { - case "basis": d += this.curveBasis (scenes); break; - case "cardinal": d += this.curveCardinal(scenes, s.tension); break; - case "monotone": d += this.curveMonotone(scenes); break; - default: curveInterpolated = false; - } - } - - if(!curveInterpolated){ - for (var i = 1 ; i < count ; i++) { - d += this.lineSegmentPath(scenes[i - 1], scenes[i]); - } - } - - var sop = stroke.opacity; - var attrs = { - 'shape-rendering': s.antialias ? null : 'crispEdges', - 'pointer-events': s.events, - 'cursor': s.cursor, - 'd': d, - 'fill': fill.color, - 'fill-opacity': fill.opacity || null, - 'stroke': stroke.color, - 'stroke-opacity': sop || null, - 'stroke-width': sop ? (s.lineWidth / this.scale) : null, - 'stroke-linecap': s.lineCap, - 'stroke-linejoin': s.lineJoin, - 'stroke-miterlimit': s.strokeMiterLimit, - 'stroke-dasharray': sop ? this.parseDasharray(s) : null - }; - - elm = this.expect(elm, 'path', scenes, 0, attrs, s.css); - - if(s.svg) this.setAttributes(elm, s.svg); - - return this.append(elm, scenes, 0); -}; - -pv.SvgScene.lineSegmentedSmart = function(elm, scenes) { - - var eventsSegments = scenes.mark.$hasHandlers ? [] : null; - - /* Visual only */ - // Iterate *visible* scene segments - elm = this.eachLineAreaSegment(elm, scenes, function(elm, scenes, from, to){ - - // Paths depend only on visibility - var paths = this.lineSegmentPaths(scenes, from, to); - var fromp = from; - - // Events segments also, depend only on visibility - if(eventsSegments){ - eventsSegments.push({ - from: from, - paths: paths - }); - } - - // Split this visual scenes segment, - // on key properties changes - var options = { - breakOnKeyChange: true, - from: from, - to: to - }; - - return this.eachLineAreaSegment(elm, scenes, options, function(elm, scenes, from, to){ - - var s1 = scenes[from]; - - var fill = s1.fillStyle; - this.addFillStyleDefinition(scenes, fill); - - var stroke = s1.strokeStyle; - this.addFillStyleDefinition(scenes, stroke); - - if(from === to){ - // Visual and events - return this.lineAreaDotAlone(elm, scenes, from); - } - - var d = this.lineJoinPaths(paths, from - fromp, to - fromp - 1); // N - 1 paths connect N points - - var sop = stroke.opacity; - var attrs = { - 'shape-rendering': s1.antialias ? null : 'crispEdges', - 'pointer-events': 'none', - 'cursor': s1.cursor, - 'd': d, - 'fill': fill.color, - 'fill-opacity': fill.opacity || null, - 'stroke': stroke.color, - 'stroke-opacity': sop || null, - 'stroke-width': sop ? (s1.lineWidth / this.scale) : null, - 'stroke-linecap': s1.lineCap, - 'stroke-linejoin': s1.lineJoin, - 'stroke-miterlimit': s1.strokeMiterLimit, - 'stroke-dasharray': sop ? this.parseDasharray(s1) : null - }; - - elm = this.expect(elm, 'path', scenes, from, attrs, s1.css); - - return this.append(elm, scenes, from); - }); - }); - - /* Events */ - if(eventsSegments){ - eventsSegments.forEach(function(segment){ - var from = segment.from; - var paths = segment.paths; - - var attrsBase = { - 'shape-rendering': 'crispEdges', - 'fill': 'rgb(127,127,127)', - 'fill-opacity': 0.005, // VML requires this much to fire events - 'stroke': 'rgb(127,127,127)', - 'stroke-opacity': 0.005, // VML idem - 'stroke-width': 5 - }; - - paths.forEach(function(path, j){ - var i = from + j; - var s = scenes[i]; - - var events = s.events; - if(events && events !== 'none'){ - var attrs = Object.create(attrsBase); - attrs['pointer-events'] = events; - attrs.cursor = s.cursor; - attrs.d = path.join(''); - - elm = this.expect(elm, 'path', scenes, i, attrs); - - elm = this.append(elm, scenes, i); - } - }, this); - }, this); - } - - return elm; -}; - -pv.SvgScene.lineSegmentedFull = function(e, scenes) { - var s = scenes[0]; - var paths; - switch (s.interpolate) { - case "basis": paths = this.curveBasisSegments(scenes); break; - case "cardinal": paths = this.curveCardinalSegments(scenes, s.tension); break; - case "monotone": paths = this.curveMonotoneSegments(scenes); break; - } - - for (var i = 0, n = scenes.length - 1; i < n; i++) { - var s1 = scenes[i], s2 = scenes[i + 1]; - - /* visible */ - if (!s1.visible || !s2.visible) continue; - var stroke = s1.strokeStyle, fill = pv.FillStyle.transparent; - if (!stroke.opacity) continue; - - /* interpolate */ - var d; - if ((s1.interpolate == "linear") && (s1.lineJoin == "miter")) { - fill = stroke; - stroke = pv.FillStyle.transparent; - d = this.pathJoin(scenes[i - 1], s1, s2, scenes[i + 2]); - } else if(paths) { - d = paths[i].join(""); - } else { - d = "M" + s1.left + "," + s1.top + this.lineSegmentPath(s1, s2); - } - - e = this.expect(e, "path", scenes, i, { - "shape-rendering": s1.antialias ? null : "crispEdges", - "pointer-events": s1.events, - "cursor": s1.cursor, - "d": d, - "fill": fill.color, - "fill-opacity": fill.opacity || null, - "stroke": stroke.color, - "stroke-opacity": stroke.opacity || null, - "stroke-width": stroke.opacity ? s1.lineWidth / this.scale : null, - "stroke-linejoin": s1.lineJoin - }); - - if(s1.svg) this.setAttributes(e, s1.svg); - if(s1.css) this.setStyle(e, s1.css); - - e = this.append(e, scenes, i); - } - return e; -}; - -/** @private Returns the path segment for the specified points. */ -pv.SvgScene.lineSegmentPath = function(s1, s2) { - var l = 1; // sweep-flag - switch (s1.interpolate) { - case "polar-reverse": - l = 0; - case "polar": { - var dx = s2.left - s1.left, - dy = s2.top - s1.top, - e = 1 - s1.eccentricity, - r = Math.sqrt(dx * dx + dy * dy) / (2 * e); - if ((e <= 0) || (e > 1)) break; // draw a straight line - return "A" + r + "," + r + " 0 0," + l + " " + s2.left + "," + s2.top; - } - case "step-before": return "V" + s2.top + "H" + s2.left; - case "step-after": return "H" + s2.left + "V" + s2.top; - } - return "L" + s2.left + "," + s2.top; -}; - -pv.SvgScene.lineSegmentPaths = function(scenes, from, to) { - var s = scenes[from]; - - var paths; - switch (s.interpolate) { - case "basis": paths = this.curveBasisSegments (scenes, from, to); break; - case "cardinal": paths = this.curveCardinalSegments(scenes, s.tension, from, to); break; - case "monotone": paths = this.curveMonotoneSegments(scenes, from, to); break; - } - - //"polar-reverse", "polar", "step-before", "step-after", and linear - if(!paths || !paths.length){ // not curve interpolation or not enough points for it - paths = []; - for (var i = from + 1 ; i <= to ; i++) { - var s1 = scenes[i - 1]; - var s2 = scenes[i ]; - paths.push(["M" + s1.left + "," + s1.top, this.lineSegmentPath(s1, s2)]); - } - } - - return paths; -}; - -/* - MITER / BEVEL JOIN calculation - - Normal line p1->p2 bounding box points (a-b-c-d) - - ^ w12 - a-----------------|--------------b ^ - | | | | - p1 <----+p12 p2 | w1 - | | | - d--------------------------------c v - - Points are added in the following order: - d -> a -> b -> c - - Depending on the position of p0 in relation to the segment p1-p2, - 'a' may be the outer corner and 'd' the inner corner, - or the opposite: - - Ex1: - outer side - - p1 ---- p2 - / - p0 inner side - - a is outer, d is inner - - Ex2: - - p0 inner side - \ - p1 ---- p2 - - outer side - - a is inner, d is outer - - ===================== - - ^ v1 - \ - am - *--a------ ... ----b - \ | | - p1 p2 - |\ | - d-*---- ... ----c - dm\ - \ - v - v1 - - - NOTE: - As yy points down, and because of the way Vector.perp() is written, - perp() corresponds to rotating 90º clockwise. - - ----- - - The miter (ratio) limit is - the limit on the ratio of the miter length to the line width. - - The miter length is the distance between the - outer corner and the inner corner of the miter. -*/ -pv.strokeMiterLimit = 4; - -/** @private Returns the miter join path for the specified points. */ -pv.SvgScene.pathJoin = function(s0, s1, s2, s3) { - /* - * P1-P2 is the current line segment. - * V is a vector that is perpendicular to the line segment, and has length lineWidth / 2. - * ABCD forms the initial bounding box of the line segment - * (i.e., the line segment if we were to do no joins). - */ - var pts = []; - var miterLimit, miterRatio, miterLength; - - var w1 = s1.lineWidth / this.scale; - var p1 = pv.vector(s1.left, s1.top); - var p2 = pv.vector(s2.left, s2.top); - - var p21 = p2.minus(p1); - var v21 = p21.perp().norm(); - var w21 = v21.times(w1 / 2); - - var a = p1.plus (w21); - var d = p1.minus(w21); - - var b = p2.plus (w21); - var c = p2.minus(w21); - - // -------------------- - - if(!s0 || !s0.visible){ - // Starting point - pts.push(d, a); - } else { - var p0 = pv.vector(s0.left, s0.top); - var p10 = p1.minus(p0); - var v10 = p10.perp().norm(); // may point inwards or outwards - - // v1 points from p1 to the inner or outer corner. - var v1 = v10.plus(v21).norm(); - - // Miter Join - // One is the outer corner, the other is the inner corner - var am = this.lineIntersect(p1, v1, a, p21); - var dm = this.lineIntersect(p1, v1, d, p21); - - // Check Miter Limit - // The line width is taken as the average of the widths - // of the p0-p1 segment and that of the p1-p2 segment. - miterLength = am.minus(dm).length(); - var w0 = s0.lineWidth / this.scale; - var w10avg = (w1 + w0) / 2; - miterRatio = miterLength / w10avg; - miterLimit = s1.strokeMiterLimit || pv.strokeMiterLimit; - if(miterRatio <= miterLimit){ - // Accept the miter join - pts.push(dm, am); - } else { - // Choose the bevel join - // v1Outer is parallel to v1, but always points outwards - var p12 = p21.times(-1); - var v1Outer = p10.norm().plus(p12.norm()).norm(); - - // The bevel intermediate point - // Place it along v1Outer, at a distance w10avg/2 from p1. - // If it were a circumference, it would have that radius. - // The inner corner is am or dm. - // The other corner is the original d or a. - var bevel10 = p1.plus(v1Outer.times(w10avg / 2)); - if(v1Outer.dot(v21) >= 0){ - // a is outer, d is inner - pts.push(dm, bevel10, a); - } else { - // d is outer, a is inner - pts.push(d, bevel10, am); - } - } - } - - // ------------------- - - if(!s3 || !s3.visible){ - // Starting point - pts.push(b, c); - } else { - var p3 = pv.vector(s3.left, s3.top); - var p32 = p3.minus(p2); - var v32 = p32.perp().norm(); - var v2 = v32.plus(v21).norm(); - - // Miter Join - var bm = this.lineIntersect(p2, v2, b, p21); - var cm = this.lineIntersect(p2, v2, c, p21); - - miterLength = bm.minus(cm).length(); - var w3 = s3.lineWidth / this.scale; - var w31avg = (w3 + w1) / 2; - miterRatio = miterLength / w31avg; - miterLimit = s2.strokeMiterLimit || pv.strokeMiterLimit; - if(miterRatio <= miterLimit){ - // Accept the miter join - pts.push(bm, cm); - } else { - // Choose a bevel join - var p23 = p32.times(-1); - var v2Outer = p21.norm().plus(p23.norm()).norm(); - var bevel31 = p2.plus(v2Outer.times(w31avg / 2)); - if(v2Outer.dot(v21) >= 0){ - // b is outer, c is inner - pts.push(b, bevel31, cm); - } else { - // c is outer, b is inner - pts.push(bm, bevel31, c); - } - } - } - - // Render pts to svg path - var pt = pts.shift(); - return "M" + pt.x + "," + pt.y + - "L" + pts.map(function(pt2){ return pt2.x + "," + pt2.y; }) - .join(" "); -}; - -/** @private Line-line intersection, per Akenine-Moller 16.16.1. */ -pv.SvgScene.lineIntersect = function(o1, d1, o2, d2) { - return o1.plus(d1.times(o2.minus(o1).dot(d2.perp()) / d1.dot(d2.perp()))); -}; - -/* Line & Area Commons */ - -pv.SvgScene.lineJoinPaths = function(paths, from, to) { - // Curve-interpolated paths of each segment - var d = paths[from].join(""); // Move And LineTo from the first step - for (var i = from + 1 ; i <= to ; i++) { - d += paths[i][1]; // LineTo of the following steps - } - - return d; -}; - -/* Draws a single circle with a diameter equal to the line width, - * when neighbour scenes are invisible. - */ -pv.SvgScene.lineAreaDotAlone = function(elm, scenes, i) { - return elm; - /* - var s = scenes[i]; - var s2; - if(i > 0){ - s2 = scenes[i-1]; - if(this.isSceneVisible(s2)){ - // Not alone - return elm; - } - } - - var last = scenes.length - 1; - if(i < last){ - s2 = scenes[i+1]; - if(this.isSceneVisible(s2)){ - // Not alone - return elm; - } - } - - var style = s.strokeStyle; - if(!style || !style.opacity){ - style = s.fillStyle; - } - var radius = Math.max(s.lineWidth / 2, 1.5) / this.scale; - - var attrs = { - 'shape-rendering': s.antialias ? null : 'crispEdges', - 'pointer-events': s.events, - 'cursor': s.cursor, - 'fill': style.color, - 'fill-opacity': style.opacity || null, - 'stroke': 'none', - 'cx': s.left, - 'cy': s.top, - 'r': radius - }; - - elm = this.expect(elm, "circle", scenes, i, attrs, s.css); - - if(s.svg) this.setAttributes(elm, s.svg); - - return this.append(elm, scenes, i); - */ -}; - -pv.SvgScene.eachLineAreaSegment = function(elm, scenes, keyArgs, lineAreaSegment) { - - if(typeof keyArgs === 'function'){ - lineAreaSegment = keyArgs; - keyArgs = null; - } - - // Besides breaking paths on visible, - // should they break on properties as well? - var breakOnKeyChange = pv.get(keyArgs, 'breakOnKeyChange', false); - var from = pv.get(keyArgs, 'from') || 0; - var to = pv.get(keyArgs, 'to', scenes.length - 1); - - var ki, kf; - if(breakOnKeyChange){ - ki = []; - kf = []; - } - - var i = from; - while(i <= to){ - - // Find the INITIAL scene - var si = scenes[i]; - if(!this.isSceneVisible(si)){ - i++; - continue; - } - - // Compute its line-area-key - if(breakOnKeyChange){ - this.lineAreaSceneKey(si, ki); - } - - // Find the FINAL scene - // the "i" in which to start the next part - var i2; - var f = i; - while(true){ - var f2 = f + 1; - if(f2 > to){ - // No next scene - // Connect i to f (possibly, i === f) - // Continue with f + 1, to make it stop... - i2 = f2; - break; - } - - var sf = scenes[f2]; - if(!this.isSceneVisible(sf)){ - // f + 1 exists but is NOT strictly visible - // Connect i to f (possibly, i === f) - // Continue with f + 2 - i2 = f2 + 1; - break; - } - - // Accept f + 1 as final point - // f > i - f = f2; - - if(breakOnKeyChange){ - this.lineAreaSceneKey(sf, kf); - if(!this.equalSceneKeys(ki, kf)){ - // Break path due to != path properties - // Connect i to f - // Continue with f - i2 = f; - break; - } - } - } - - elm = lineAreaSegment.call(this, elm, scenes, i, f, keyArgs); - - // next part - i = i2; - } - - return elm; -}; - -pv.SvgScene.lineAreaSceneKey = function(s, k){ - k[0] = s.fillStyle.key; - k[1] = s.strokeStyle.key; - k[2] = s.lineWidth; - k[3] = (s.strokeDasharray || 'none'); - k[4] = s.interpolate; - return k; -}; - -pv.SvgScene.isSceneVisible = function(s){ - return s.visible && - (s.fillStyle.opacity > 0 || s.strokeStyle.opacity > 0); -}; - -pv.SvgScene.equalSceneKeys = function(ka, kb){ - for(var i = 0, K = ka.length ; i < K ; i++){ - if(ka[i] !== kb[i]){ - return false; - } - } - return true; -}; -pv.SvgScene.panel = function(scenes) { - var g = scenes.$g, e = g && g.firstChild; - var complete = false; - for (var i = 0; i < scenes.length; i++) { - var s = scenes[i]; - - /* visible */ - if (!s.visible) continue; - - /* svg */ - if (!scenes.parent) { - if(pv.renderer() !== "batik") { - s.canvas.style.display = "inline-block"; - } - if (g && (g.parentNode != s.canvas)) { - g = s.canvas.firstChild; - e = g && g.firstChild; - } - if (!g) { - g = this.create(pv.renderer() !== "batik" ? "svg":"g"); - g.setAttribute("font-size", "10px"); - g.setAttribute("font-family", "sans-serif"); - g.setAttribute("fill", "none"); - g.setAttribute("stroke", "none"); - g.setAttribute("stroke-width", 1.5); - - // Prevent selecting VML elements when dragging - - // Supported by IE10 SVG - g.setAttribute("style", "-webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;"); - - if (typeof g.onselectstart !== 'undefined') { - // IE9 SVG - g.setAttribute('unselectable', 'on'); - g.onselectstart = function(){ return false; }; - } - - if (pv.renderer() === "svgweb") { // SVGWeb requires a separate mechanism for setting event listeners. - // width/height can't be set on the fragment - g.setAttribute("width", s.width + s.left + s.right); - g.setAttribute("height", s.height + s.top + s.bottom); - - var frag = document.createDocumentFragment(true); - - g.addEventListener('SVGLoad', function() { - /** - * This hack was based off a suggestion by Idearat - * on the protovis mailing list to work around the SVGWeb - * SVGLoad event being called prior to the scene graph being - * completed, and causing errors when listeners executed. As - * described by him: - * - So I've been running into a consistent issue with protovis + svgweb - integration where I get an empty (white screen) as many folks have - previously reported. - - The section of that code with the if (pv.renderer() == "svgweb") block - follows the advice for SVGWeb integration which says to a) - addEventListener('SVGLoad', ...) and to use svgweb.appendChild(). The - problem is that the svgweb.appendChild call immediately turns around - and invokes any event listeners on the newly appended nodes...and the - "frag" can still be empty at that point. This can be confirmed in a - debugger's stack trace. - - This new version effectively says run the (now embedded in func) - handler logic immediately if complete, otherwise try again shortly - via setTimeout every 100ms until we've completed the scene graph. - - I've run this through a number of graphs within a complex application - with PHP, JQuery, YUI and other libs in the mix and it consistently - draws the graphs with no more white/blank display. - - * Until a better solution comes along, lets use this. - */ - var me = this; - (function () { - if (complete) { - complete = false; - me.appendChild(frag); - for (var j = 0; j < pv.Scene.events.length; j++) { - me.addEventListener(pv.Scene.events[j], pv.SvgScene.dispatch, false); - } - scenes.$g = me; - scenes.$g.__ready = true; - } else { - setTimeout(arguments.callee, 10); - } - })(); - - }, false); - - svgweb.appendChild (g, s.canvas); - g = frag; - } else { - for (var j = 0; j < this.events.length; j++) { - g.addEventListener(this.events[j], this.dispatch, false); - } - g = s.canvas.appendChild(g); - g.__ready = true; - } - - e = g.firstChild; - } - scenes.$g = g; - if (g.__ready) { - g.setAttribute("width", s.width + s.left + s.right); - g.setAttribute("height", s.height + s.top + s.bottom); - } - } - - /* clip (nest children) */ - if (s.overflow == "hidden") { - var id = pv.id().toString(36), - c = this.expect(e, "g", scenes, i, {"clip-path": "url(#" + id + ")"}); - if (!c.parentNode) g.appendChild(c); - scenes.$g = g = c; - e = c.firstChild; - - e = this.expect(e, "clipPath", scenes, i, {"id": id}); - var r = e.firstChild || e.appendChild(this.create("rect")); - r.setAttribute("x", s.left); - r.setAttribute("y", s.top); - r.setAttribute("width", s.width); - r.setAttribute("height", s.height); - if (!e.parentNode) g.appendChild(e); - e = e.nextSibling; - } - - /* fill */ - e = this.fill(e, scenes, i); - - /* transform (push) */ - var k = this.scale, - t = s.transform, - x = s.left + t.x, - y = s.top + t.y; - this.scale *= t.k; - - /* children */ - this.eachChild(scenes, i, function(childScenes){ - childScenes.$g = e = this.expect(e, "g", scenes, i, { - "transform": "translate(" + x + "," + y + ")" + - (t.k != 1 ? " scale(" + t.k + ")" : "") - }); - - this.updateAll(childScenes); - if (!e.parentNode) g.appendChild(e); - e = e.nextSibling; - }); - - /* transform (pop) */ - this.scale = k; - - /* stroke */ - e = this.stroke(e, scenes, i); - - /* clip (restore group) */ - if (s.overflow == "hidden") { - scenes.$g = g = c.parentNode; - e = c.nextSibling; - } - } - complete = true; - return e; -}; - -pv.SvgScene.eachChild = function(scenes, i, fun, ctx){ - if(scenes.mark.zOrderChildCount){ - var sorted = scenes[i].children.slice(0); - sorted.sort(function(scenes1, scenes2){ // sort ascending - var compare = scenes1.mark._zOrder - scenes2.mark._zOrder; - if(compare === 0){ - // Preserve original order for same zOrder childs - compare = scenes1.childIndex - scenes2.childIndex; - } - return compare; - }); - - sorted.forEach(fun, ctx || this); - } else { - scenes[i].children.forEach(fun, ctx || this); - } -}; - -pv.SvgScene.fill = function(e, scenes, i) { - this.removeFillStyleDefinitions(scenes); - - var s = scenes[i], fill = s.fillStyle; - if (fill.opacity || s.events == "all") { - - if (fill.type && fill.type !== 'solid') { - this.addFillStyleDefinition(scenes,fill); - } - - e = this.expect(e, "rect", scenes, i, { - "shape-rendering": s.antialias ? null : "crispEdges", - "pointer-events": s.events, - "cursor": s.cursor, - "x": s.left, - "y": s.top, - "width": s.width, - "height": s.height, - "fill": fill.color, - "fill-opacity": fill.opacity, - "stroke": null - }); - e = this.append(e, scenes, i); - } - return e; -}; - -pv.SvgScene.stroke = function(e, scenes, i) { - var s = scenes[i], stroke = s.strokeStyle; - if (stroke.opacity || s.events == "all") { - e = this.expect(e, "rect", scenes, i, { - "shape-rendering": s.antialias ? null : "crispEdges", - "pointer-events": s.events == "all" ? "stroke" : s.events, - "cursor": s.cursor, - "x": s.left, - "y": s.top, - "width": Math.max(1E-10, s.width), - "height": Math.max(1E-10, s.height), - "fill": null, - "stroke": stroke.color, - "stroke-opacity": stroke.opacity, - "stroke-width": s.lineWidth / this.scale, - "stroke-linecap": s.lineCap, - "stroke-dasharray": stroke.opacity ? this.parseDasharray(s) : null - }); - e = this.append(e, scenes, i); - } - return e; -}; -pv.SvgScene.minRuleLineWidth = 1; - -pv.SvgScene.rule = function(scenes) { - var e = scenes.$g.firstChild; - for (var i = 0; i < scenes.length; i++) { - var s = scenes[i]; - - /* visible */ - if (!s.visible) continue; - var stroke = s.strokeStyle; - if (!stroke.opacity) continue; - - var lineWidth = s.lineWidth; - if(lineWidth < 1e-10){ - lineWidth = 0; - } else { - lineWidth = Math.max(this.minRuleLineWidth, lineWidth / this.scale); - } - - e = this.expect(e, "line", scenes, i, { - "shape-rendering": s.antialias ? null : "crispEdges", - "pointer-events": s.events, - "cursor": s.cursor, - "x1": s.left, - "y1": s.top, - "x2": s.left + s.width, - "y2": s.top + s.height, - "stroke": stroke.color, - "stroke-opacity": stroke.opacity, - "stroke-width": lineWidth, - "stroke-linecap": s.lineCap, - "stroke-dasharray": stroke.opacity ? this.parseDasharray(s) : null - }); - - if(s.svg) this.setAttributes(e, s.svg); - if(s.css) this.setStyle(e, s.css); - - e = this.append(e, scenes, i); - } - return e; -}; -pv.SvgScene.wedge = function(scenes) { - var e = scenes.$g.firstChild; - - this.removeFillStyleDefinitions(scenes); - - for (var i = 0; i < scenes.length; i++) { - var s = scenes[i]; - - /* visible */ - if (!s.visible) continue; - var fill = s.fillStyle, stroke = s.strokeStyle; - if (!fill.opacity && !stroke.opacity) continue; - - /* points */ - var r1 = s.innerRadius, r2 = s.outerRadius, a = Math.abs(s.angle), p; - if (a >= 2 * Math.PI) { - if (r1) { - p = "M0," + r2 - + "A" + r2 + "," + r2 + " 0 1,1 0," + (-r2) - + "A" + r2 + "," + r2 + " 0 1,1 0," + r2 - + "M0," + r1 - + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1) - + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 - + "Z"; - } else { - p = "M0," + r2 - + "A" + r2 + "," + r2 + " 0 1,1 0," + (-r2) - + "A" + r2 + "," + r2 + " 0 1,1 0," + r2 - + "Z"; - } - } else { - var sa = Math.min(s.startAngle, s.endAngle), - ea = Math.max(s.startAngle, s.endAngle), - c1 = Math.cos(sa), c2 = Math.cos(ea), - s1 = Math.sin(sa), s2 = Math.sin(ea); - if (r1) { - p = "M" + r2 * c1 + "," + r2 * s1 - + "A" + r2 + "," + r2 + " 0 " - + ((a < Math.PI) ? "0" : "1") + ",1 " - + r2 * c2 + "," + r2 * s2 - + "L" + r1 * c2 + "," + r1 * s2 - + "A" + r1 + "," + r1 + " 0 " - + ((a < Math.PI) ? "0" : "1") + ",0 " - + r1 * c1 + "," + r1 * s1 + "Z"; - } else { - p = "M" + r2 * c1 + "," + r2 * s1 - + "A" + r2 + "," + r2 + " 0 " - + ((a < Math.PI) ? "0" : "1") + ",1 " - + r2 * c2 + "," + r2 * s2 + "L0,0Z"; - } - } - - if (fill.type && fill.type !== 'solid') { - this.addFillStyleDefinition(scenes,fill); - } - - if (stroke.type && stroke.type != 'solid') { - this.addFillStyleDefinition(scenes,stroke); - } - - e = this.expect(e, "path", scenes, i, { - "shape-rendering": s.antialias ? null : "crispEdges", - "pointer-events": s.events, - "cursor": s.cursor, - "transform": "translate(" + s.left + "," + s.top + ")", - "d": p, - "fill": fill.color, - "fill-rule": "evenodd", - "fill-opacity": fill.opacity || null, - "stroke": stroke.color, - "stroke-opacity": stroke.opacity || null, - "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null, - "stroke-linejoin": s.lineJoin, - "stroke-miterlimit": s.strokeMiterLimit, - "stroke-linecap": s.lineCap, - "stroke-dasharray": stroke.opacity ? this.parseDasharray(s) : null - }); - - if(s.svg) this.setAttributes(e, s.svg); - if(s.css) this.setStyle(e, s.css); - - e = this.append(e, scenes, i); - } - - /* - // DEBUG BEG - var mark = scenes.mark; - for (var i = 0; i < scenes.length; i+=2) { - var shape = mark.getShape(scenes, i); - - // POINTS - var points = shape.points(); - points.forEach(function(p){ - e = this.expect(e, 'circle', scenes, i, { - cx: p.x, - cy: p.y, - r: 2, - fill: 'black' - }); - e = this.append(e, scenes, i); - }, this); - - // EDGES - var edges = shape.edges(); - edges.forEach(function(edge){ - if(edge instanceof pv.Shape.Line){ - e = this.expect(e, 'path', scenes, 0, { - d: "M" + edge.x + "," + edge.y + "L" + edge.x2 + "," + edge.y2, - stroke: 'green', - 'stroke-width': 1 - }); - - } else if (edge instanceof pv.Shape.Arc){ - var sa = Math.min(edge.startAngle, edge.endAngle), - ea = Math.max(edge.startAngle, edge.endAngle), - c1 = Math.cos(sa), c2 = Math.cos(ea), - s1 = Math.sin(sa), s2 = Math.sin(ea), - r = edge.radius; - - var p = "M" + r * c1 + "," + r * s1 + - "A" + r + "," + r + " 0 " - + ((edge.angleSpan < Math.PI) ? "0" : "1") + ",1 " - + r * c2 + "," + r * s2; - - e = this.expect(e, 'path', scenes, 0, { - d: p, - transform: "translate(" + edge.x + "," + edge.y + ")", - stroke: 'red', - 'stroke-width': 1 - }); - } - - e = this.append(e, scenes, i); - }, this); - } - // DEBUG END - */ - return e; -}; -/** - * Constructs a new mark with default properties. Marks, with the exception of - * the root panel, are not typically constructed directly; instead, they are - * added to a panel or an existing mark via {@link pv.Mark#add}. - * - * @class Represents a data-driven graphical mark. The Mark class is - * the base class for all graphical marks in Protovis; it does not provide any - * specific rendering functionality, but together with {@link Panel} establishes - * the core framework. - * - *

Concrete mark types include familiar visual elements such as bars, lines - * and labels. Although a bar mark may be used to construct a bar chart, marks - * know nothing about charts; it is only through their specification and - * composition that charts are produced. These building blocks permit many - * combinatorial possibilities. - * - *

Marks are associated with data: a mark is generated once per - * associated datum, mapping the datum to visual properties such as - * position and color. Thus, a single mark specification represents a set of - * visual elements that share the same data and visual encoding. The type of - * mark defines the names of properties and their meaning. A property may be - * static, ignoring the associated datum and returning a constant; or, it may be - * dynamic, derived from the associated datum or index. Such dynamic encodings - * can be specified succinctly using anonymous functions. Special properties - * called event handlers can be registered to add interactivity. - * - *

Protovis uses inheritance to simplify the specification of related - * marks: a new mark can be derived from an existing mark, inheriting its - * properties. The new mark can then override properties to specify new - * behavior, potentially in terms of the old behavior. In this way, the old mark - * serves as the prototype for the new mark. Most mark types share the - * same basic properties for consistency and to facilitate inheritance. - * - *

The prioritization of redundant properties is as follows:

    - * - *
  1. If the width property is not specified (i.e., null), its value - * is the width of the parent panel, minus this mark's left and right margins; - * the left and right margins are zero if not specified. - * - *
  2. Otherwise, if the right margin is not specified, its value is - * the width of the parent panel, minus this mark's width and left margin; the - * left margin is zero if not specified. - * - *
  3. Otherwise, if the left property is not specified, its value is - * the width of the parent panel, minus this mark's width and the right margin. - * - *
This prioritization is then duplicated for the height, - * bottom and top properties, respectively. - * - *

While most properties are variable, some mark types, such as lines - * and areas, generate a single visual element rather than a distinct visual - * element per datum. With these marks, some properties may be fixed. - * Fixed properties can vary per mark, but not per datum! These - * properties are evaluated solely for the first (0-index) datum, and typically - * are specified as a constant. However, it is valid to use a function if the - * property varies between panels or is dynamically generated. - * - *

See also the Protovis guide. - */ -pv.Mark = function() { - /* - * TYPE 0 constant defs - * TYPE 1 function defs - * TYPE 2 constant properties - * TYPE 3 function properties - * in order of evaluation! - */ - this.$properties = []; - this.$propertiesMap = {}; - this.$handlers = {}; -}; - -/** @private Records which properties are defined on this mark type. */ -pv.Mark.prototype.properties = {}; - -/** @private Records the cast function for each property. */ -pv.Mark.cast = {}; - -/** - * @private Defines and registers a property method for the property with the - * given name. This method should be called on a mark class prototype to define - * each exposed property. (Note this refers to the JavaScript - * prototype, not the Protovis mark prototype, which is the {@link - * #proto} field.) - * - *

The created property method supports several modes of invocation:

    - * - *
  1. If invoked with a Function argument, this function is evaluated - * for each associated datum. The return value of the function is used as the - * computed property value. The context of the function (this) is this - * mark. The arguments to the function are the associated data of this mark and - * any enclosing panels. For example, a linear encoding of numerical data to - * height is specified as - * - *
    m.height(function(d) d * 100);
    - * - * The expression d * 100 will be evaluated for the height property of - * each mark instance. The return value of the property method (e.g., - * m.height) is this mark (m)).

    - * - *

  2. If invoked with a non-function argument, the property is treated as a - * constant. The return value of the property method (e.g., m.height) - * is this mark.

    - * - *

  3. If invoked with no arguments, the computed property value for the current - * mark instance in the scene graph is returned. This facilitates property - * chaining, where one mark's properties are defined in terms of another's. - * For example, to offset a mark's location from its prototype, you might say - * - *
    m.top(function() this.proto.top() + 10);
    - * - * Note that the index of the mark being evaluated (in the above example, - * this.proto) is inherited from the Mark class and set by - * this mark. So, if the fifth element's top property is being evaluated, the - * fifth instance of this.proto will similarly be queried for the value - * of its top property. If the mark being evaluated has a different number of - * instances, or its data is unrelated, the behavior of this method is - * undefined. In these cases it may be better to index the scene - * explicitly to specify the exact instance. - * - *

Property names should follow standard JavaScript method naming - * conventions, using lowerCamel-style capitalization. - * - *

In addition to creating the property method, every property is registered - * in the {@link #properties} map on the prototype. Although this is an - * instance field, it is considered immutable and shared by all instances of a - * given mark type. The properties map can be queried to see if a mark - * type defines a particular property, such as width or height. - * - * @param {string} name the property name. - * @param {function} [cast] the cast function for this property. - */ -pv.Mark.prototype.property = function(name, cast) { - if (!this.hasOwnProperty("properties")) { - this.properties = pv.extend(this.properties); - } - this.properties[name] = true; - - /* - * Define the setter-getter globally, since the default behavior should be the - * same for all properties, and since the Protovis inheritance chain is - * independent of the JavaScript inheritance chain. For example, anchors - * define a "name" property that is evaluated on derived marks, even though - * those marks don't normally have a name. - */ - pv.Mark.prototype.propertyMethod(name, false, pv.Mark.cast[name] = cast); - return this; -}; - -// Adapted from pv.Layout#property -/** - * Defines a local property with the specified name and cast. - * Note that although the property method is only defined locally, - * the cast function is global, - * which is necessary since properties are inherited! - * - * @param {string} name the property name. - * @param {function} [cast] the cast function for this property. - */ -pv.Mark.prototype.localProperty = function(name, cast) { - if (!this.hasOwnProperty("properties")) { - this.properties = pv.extend(this.properties); - } - this.properties[name] = true; - - var currCast = pv.Mark.cast[name]; - if(cast){ - pv.Mark.cast[name] = currCast = cast; - } - - this.propertyMethod(name, false, currCast); - return this; -}; - -/** - * @private Defines a setter-getter for the specified property. - * - *

If a cast function has been assigned to the specified property name, the - * property function is wrapped by the cast function, or, if a constant is - * specified, the constant is immediately cast. Note, however, that if the - * property value is null, the cast function is not invoked. - * - * @param {string} name the property name. - * @param {boolean} [def] whether is a property or a def. - * @param {function} [cast] the cast function for this property. - */ -pv.Mark.prototype.propertyMethod = function(name, def, cast) { - if (!cast) cast = pv.Mark.cast[name]; - - this[name] = function(v, tag) { - /* When arguments are specified, set the property/def value. */ - - /* DEF */ - if (def && this.scene) { - var defs = this.scene.defs; - - if (arguments.length) { - defs[name] = { - id: (v == null) ? 0 : pv.id(), - value: ((v != null) && cast) ? cast(v) : v - }; - - return this; - } - - return defs[name] ? defs[name].value : null; - } - - /* PROP */ - if (arguments.length) { - this.setPropertyValue(name, v, def, cast, /* chain */false, tag); - return this; - } - - // Listening to function property dependencies? - var propEval = pv.propertyEval; - if(propEval) { - var binds = this.binds; - var propRead = binds.properties[name]; - if(propRead){ - var net = binds.net; - var readNetIndex = net[name]; - if(readNetIndex == null){ - readNetIndex = net[name] = 0; - } - - (propRead.dependents || (propRead.dependents = {})) - [propEval.name] = true; - - (pv.propertyEvalDependencies || (pv.propertyEvalDependencies = {})) - [name] = true; - - // evalNetIndex must be at least one higher than readNetIndex - if(readNetIndex >= pv.propertyEvalNetIndex){ - pv.propertyEvalNetIndex = readNetIndex + 1; - } - } - } - - return this.instance()[name]; - }; -}; - -/** @private Creates and returns a wrapper function to call a property function and a property cast. */ -pv.Mark.funPropertyCaller = function(fun, cast){ - // Avoiding the use of arguments object to try to speed things up - var stack = pv.Mark.stack; - - return function(){ - var value = fun.apply(this, stack); - return value != null ? cast(value) : value; // some things depend on the null/undefined distinction - }; -}; - -/** @private Sets the value of the property name to v. */ -pv.Mark.prototype.setPropertyValue = function(name, v, def, cast, chain, tag){ - /* bit 0: 0 = value, 1 = function - * bit 1: 0 = def, 1 = prop - * ------------------------------ - * 00 - 0 - def - value - * 01 - 1 - def - function - * 10 - 2 - prop - value - * 11 - 3 - prop - function - * - * x << 1 <=> floor(x) * 2 - * - * true << 1 -> 2 - 10 - * false << 1 -> 0 - 00 - */ - var type = !def << 1 | (typeof v === "function"); - // A function and cast? - if(type & 1 && cast){ - v = pv.Mark.funPropertyCaller(v, cast); - } else if(v != null && cast){ - v = cast(v); - } - - // ------ - - var propertiesMap = this.$propertiesMap; - var properties = this.$properties; - - var p = { - name: name, - id: pv.id(), - value: v, - type: type, - tag: tag - }; - - var specified = propertiesMap[name]; - - propertiesMap[name] = p; - - if(specified){ - // Find it and remove it - for (var i = 0; i < properties.length; i++) { - if (properties[i] === specified) { - properties.splice(i, 1); - break; - } - } - } - - properties.push(p); - - if(chain && specified && type === 3){ // is a prop fun - p.proto = specified; - p.root = specified.root || specified; - } - - return p; -}; - -pv.Mark.prototype.intercept = function(name, v, keyArgs){ - this.setPropertyValue( - name, - v, - /* def */ false, - pv.get(keyArgs, 'noCast') ? null : pv.Mark.cast[name], - /* chain*/ true, - pv.get(keyArgs, 'tag')); - - return this; -}; - -/** - * Gets the static value of a property, without evaluation. - * @param {string} name the property name. - * @type any - */ -pv.Mark.prototype.propertyValue = function(name, inherit) { - var p = this.$propertiesMap[name]; - if(p){ - return p.value; - } - - // This mimics the way #bind works - if(inherit){ - if(this.proto){ - var value = this.proto.propertyValueRecursive(name); - if(value !== undefined){ - return value; - } - } - - return this.defaults.propertyValueRecursive(name); - } - - //return undefined; -}; - -/** @private */ -pv.Mark.prototype.propertyValueRecursive = function(name) { - var p = this.$propertiesMap[name]; - if(p){ - return p.value; - } - - if(this.proto){ - return this.proto.propertyValueRecursive(name); - } - //return undefined; -}; - -/** @private Stores the current data stack. */ -//must be declared before defaults, below -pv.Mark.stack = []; - -/* Define all global properties. */ -pv.Mark.prototype - .property("data") - .property("visible", Boolean) - // CSS attributes pass-through - .property("css", Object) - // SVG attributes pass-through - .property("svg", Object) - .property("left", Number) - .property("right", Number) - .property("top", Number) - .property("bottom", Number) - .property("cursor", String) - .property("title", String) - .property("reverse", Boolean) - .property("antialias", Boolean) - .property("events", String) - .property("id", String); - -/** - * The mark type; a lower camelCase name. The type name controls rendering - * behavior, and unless the rendering engine is extended, must be one of the - * built-in concrete mark types: area, bar, dot, image, label, line, panel, - * rule, or wedge. - * - * @type string - * @name pv.Mark.prototype.type - */ - -/** - * The mark prototype, possibly undefined, from which to inherit property - * functions. The mark prototype is not necessarily of the same type as this - * mark. Any properties defined on this mark will override properties inherited - * either from the prototype or from the type-specific defaults. - * - * @type pv.Mark - * @name pv.Mark.prototype.proto - */ - -/** - * The mark anchor target, possibly undefined. - * - * @type pv.Mark - * @name pv.Mark.prototype.target - */ - -/** - * The enclosing parent panel. The parent panel is generally undefined only for - * the root panel; however, it is possible to create "offscreen" marks that are - * used only for inheritance purposes. - * - * @type pv.Panel - * @name pv.Mark.prototype.parent - */ - -/** - * The child index. -1 if the enclosing parent panel is null; otherwise, the - * zero-based index of this mark into the parent panel's children array. - * - * @type number - */ -pv.Mark.prototype.childIndex = -1; - -/** - * The mark index. The value of this field depends on which instance (i.e., - * which element of the data array) is currently being evaluated. During the - * build phase, the index is incremented over each datum; when handling events, - * the index is set to the instance that triggered the event. - * - * @type number - */ -pv.Mark.prototype.index = -1; - -/** - * The current scale factor, based on any enclosing transforms. The current - * scale can be used to create scale-independent graphics. For example, to - * define a dot that has a radius of 10 irrespective of any zooming, say: - * - *

dot.shapeRadius(function() 10 / this.scale)
- * - * Note that the stroke width and font size are defined irrespective of scale - * (i.e., in screen space) already. Also note that when a transform is applied - * to a panel, the scale affects only the child marks, not the panel itself. - * - * @type number - * @see pv.Panel#transform - */ -pv.Mark.prototype.scale = 1; - -/** - * Affects the drawing order amongst sibling marks. - * Evaluation order is not affected. - * A higher Z order value is drawn on top of a lower Z order value. - * - * @type number - * @private - */ -pv.Mark.prototype._zOrder = 0; - -/** - * @private The scene graph. The scene graph is an array of objects; each object - * (or "node") corresponds to an instance of this mark and an element in the - * data array. The scene graph can be traversed to lookup previously-evaluated - * properties. - * - * @name pv.Mark.prototype.scene - */ - -/** - * The root parent panel. This may be undefined for "offscreen" marks that are - * created for inheritance purposes only. - * - * @type pv.Panel - * @name pv.Mark.prototype.root - */ - -/** - * The data property; an array of objects. The size of the array determines the - * number of marks that will be instantiated; each element in the array will be - * passed to property functions to compute the property values. Typically, the - * data property is specified as a constant array, such as - * - *
m.data([1, 2, 3, 4, 5]);
- * - * However, it is perfectly acceptable to define the data property as a - * function. This function might compute the data dynamically, allowing - * different data to be used per enclosing panel. For instance, in the stacked - * area graph example (see {@link #scene}), the data function on the area mark - * dereferences each series. - * - * @type array - * @name pv.Mark.prototype.data - */ - -/** - * The visible property; a boolean determining whether or not the mark instance - * is visible. If a mark instance is not visible, its other properties will not - * be evaluated. Similarly, for panels no child marks will be rendered. - * - * @type boolean - * @name pv.Mark.prototype.visible - */ - -/** - * The left margin; the distance, in pixels, between the left edge of the - * enclosing panel and the left edge of this mark. Note that in some cases this - * property may be redundant with the right property, or with the conjunction of - * right and width. - * - * @type number - * @name pv.Mark.prototype.left - */ - -/** - * The right margin; the distance, in pixels, between the right edge of the - * enclosing panel and the right edge of this mark. Note that in some cases this - * property may be redundant with the left property, or with the conjunction of - * left and width. - * - * @type number - * @name pv.Mark.prototype.right - */ - -/** - * The top margin; the distance, in pixels, between the top edge of the - * enclosing panel and the top edge of this mark. Note that in some cases this - * property may be redundant with the bottom property, or with the conjunction - * of bottom and height. - * - * @type number - * @name pv.Mark.prototype.top - */ - -/** - * The bottom margin; the distance, in pixels, between the bottom edge of the - * enclosing panel and the bottom edge of this mark. Note that in some cases - * this property may be redundant with the top property, or with the conjunction - * of top and height. - * - * @type number - * @name pv.Mark.prototype.bottom - */ - -/** - * The cursor property; corresponds to the CSS cursor property. This is - * typically used in conjunction with event handlers to indicate interactivity. - * - * @type string - * @name pv.Mark.prototype.cursor - * @see CSS2 cursor - */ - -/** - * The title property; corresponds to the HTML/SVG title property, allowing the - * general of simple plain text tooltips. - * - * @type string - * @name pv.Mark.prototype.title - */ - -/** - * The events property; corresponds to the SVG pointer-events property, - * specifying how the mark should participate in mouse events. The default value - * is "painted". Supported values are: - * - *

"painted": The given mark may receive events when the mouse is over a - * "painted" area. The painted areas are the interior (i.e., fill) of the mark - * if a 'fillStyle' is specified, and the perimeter (i.e., stroke) of the mark - * if a 'strokeStyle' is specified. - * - *

"all": The given mark may receive events when the mouse is over either the - * interior (i.e., fill) or the perimeter (i.e., stroke) of the mark, regardless - * of the specified fillStyle and strokeStyle. - * - *

"none": The given mark may not receive events. - * - * @type string - * @name pv.Mark.prototype.events - */ - -/** - * The reverse property; a boolean determining whether marks are ordered from - * front-to-back or back-to-front. SVG does not support explicit z-ordering; - * shapes are rendered in the order they appear. Thus, by default, marks are - * rendered in data order. Setting the reverse property to false reverses the - * order in which they are rendered; however, the properties are still evaluated - * (i.e., built) in forward order. - * - * @type boolean - * @name pv.Mark.prototype.reverse - */ - -/** - * The instance identifier, for correspondence across animated transitions. If - * no identifier is specified, correspondence is determined using the mark - * index. Identifiers are not global, but local to a given mark. - * - * @type String - * @name pv.Mark.prototype.id - */ - -/** - * Default properties for all mark types. By default, the data array is the - * parent data as a single-element array; if the data property is not specified, - * this causes each mark to be instantiated as a singleton with the parents - * datum. The visible property is true by default, and the reverse property is - * false. - * - * @type pv.Mark - */ -pv.Mark.prototype.defaults = new pv.Mark() - .data(function(d) { return [d]; }) - .visible(true) - .antialias(true) - .events("painted"); - -/** - * Sets the prototype of this mark to the specified mark. Any properties not - * defined on this mark may be inherited from the specified prototype mark, or - * its prototype, and so on. The prototype mark need not be the same type of - * mark as this mark. (Note that for inheritance to be useful, properties with - * the same name on different mark types should have equivalent meaning.) - * - * @param {pv.Mark} proto the new prototype. - * @returns {pv.Mark} this mark. - * @see #add - */ -pv.Mark.prototype.extend = function(proto) { - this.proto = proto; - this.target = proto.target; - return this; -}; - -/** - * Adds a new mark of the specified type to the enclosing parent panel, whilst - * simultaneously setting the prototype of the new mark to be this mark. - * - * @param {function} type the type of mark to add; a constructor, such as - * pv.Bar. - * @returns {pv.Mark} the new mark. - * @see #extend - */ -pv.Mark.prototype.add = function(type) { - return this.parent.add(type).extend(this); -}; - -/** - * Defines a custom property on this mark. Custom properties are currently - * fixed, in that they are initialized once per mark set (i.e., per parent panel - * instance). Custom properties can be used to store local state for the mark, - * such as data needed by other properties (e.g., a custom scale) or interaction - * state. - * - *

WARNING We plan on changing this feature in a future release to define - * standard properties, as opposed to fixed properties that behave - * idiosincratically within event handlers. Furthermore, we recommend storing - * state in an external data structure, rather than tying it to the - * visualization specification as with defs. - * - * @param {string} name the name of the local variable. - * @param {function} [v] an optional initializer; may be a constant or a - * function. - */ -pv.Mark.prototype.def = function(name, v) { - this.propertyMethod(name, true); - return this[name](arguments.length > 1 ? v : null); -}; - -/** - * Affects the drawing order amongst sibling marks. - * Evaluation order is not affected. - * A higher Z order value is drawn on top of a lower Z order value. - * - * @param {number} zOrder the Z order of the mark. - * @type number - */ -pv.Mark.prototype.zOrder = function(zOrder){ - if(!arguments.length){ - return this._zOrder; - } - - zOrder = (+zOrder) || 0; // NaN -> 0 - - if(this._zOrder !== zOrder){ - - if(this._zOrder !== 0 && this.parent){ - this.parent.zOrderChildCount--; - } - - this._zOrder = zOrder; - - if(this._zOrder !== 0 && this.parent){ - this.parent.zOrderChildCount++; - } - } - - return this; -}; - -/** - * Returns an anchor with the specified name. All marks support the five - * standard anchor names:

    - * - *
  • top - *
  • left - *
  • center - *
  • bottom - *
  • right - * - *
In addition to positioning properties (left, right, top bottom), the - * anchors support text rendering properties (text-align, text-baseline). Text is - * rendered to appear inside the mark by default. - * - *

To facilitate stacking, anchors are defined in terms of their opposite - * edge. For example, the top anchor defines the bottom property, such that the - * mark extends upwards; the bottom anchor instead defines the top property, - * such that the mark extends downwards. See also {@link pv.Layout.Stack}. - * - *

While anchor names are typically constants, the anchor name is a true - * property, which means you can specify a function to compute the anchor name - * dynamically. See the {@link pv.Anchor#name} property for details. - * - * @param {string} name the anchor name; either a string or a property function. - * @returns {pv.Anchor} the new anchor. - */ -pv.Mark.prototype.anchor = function(name) { - if (!name) name = "center"; // default anchor name - return new pv.Anchor(this) - .name(name) - .data(function() { - return this.scene.target.map(function(s) { return s.data; }); - }) - .visible(function() { - return this.scene.target[this.index].visible; - }) - .id(function() { - return this.scene.target[this.index].id; - }) - .left(function() { - var s = this.scene.target[this.index], w = s.width || 0; - switch (this.name()) { - case "bottom": - case "top": - case "center": return s.left + w / 2; - case "left": return null; - } - return s.left + w; - }) - .top(function() { - var s = this.scene.target[this.index], h = s.height || 0; - switch (this.name()) { - case "left": - case "right": - case "center": return s.top + h / 2; - case "top": return null; - } - return s.top + h; - }) - .right(function() { - var s = this.scene.target[this.index]; - return this.name() == "left" ? s.right + (s.width || 0) : null; - }) - .bottom(function() { - var s = this.scene.target[this.index]; - return this.name() == "top" ? s.bottom + (s.height || 0) : null; - }) - .textAlign(function() { - switch (this.name()) { - case "bottom": - case "top": - case "center": return "center"; - case "right": return "right"; - } - return "left"; - }) - .textBaseline(function() { - switch (this.name()) { - case "right": - case "left": - case "center": return "middle"; - case "top": return "top"; - } - return "bottom"; - }); -}; - -/** @deprecated Replaced by {@link #target}. */ -pv.Mark.prototype.anchorTarget = function() { - return this.target; -}; - -/** - * Alias for setting the left, right, top and bottom properties simultaneously. - * - * @see #left - * @see #right - * @see #top - * @see #bottom - * @returns {pv.Mark} this. - */ -pv.Mark.prototype.margin = function(n) { - return this.left(n).right(n).top(n).bottom(n); -}; - -/** - * @private Returns the current instance of this mark in the scene graph. This - * is typically equivalent to this.scene[this.index], however if the - * scene or index is unset, the default instance of the mark is returned. If no - * default is set, the default is the last instance. Similarly, if the scene or - * index of the parent panel is unset, the default instance of this mark in the - * last instance of the enclosing panel is returned, and so on. - * - * @returns a node in the scene graph. - */ -pv.Mark.prototype.instance = function(defaultIndex) { - var scene = this.scene || this.parent.instance(-1).children[this.childIndex], - index = !arguments.length || this.hasOwnProperty("index") ? this.index : defaultIndex; - return scene[index < 0 ? scene.length - 1 : index]; -}; - -/** - * @private Find the instances of this mark that match source. - * - * @see pv.Anchor - */ -pv.Mark.prototype.instances = function(source) { - var mark = this, index = [], scene; - - /* Mirrored descent. */ - while (!(scene = mark.scene)) { - source = source.parent; - index.push({index: source.index, childIndex: mark.childIndex}); - mark = mark.parent; - } - while (index.length) { - var i = index.pop(); - scene = scene[i.index].children[i.childIndex]; - } - - /* - * When the anchor target is also an ancestor, as in the case of adding - * to a panel anchor, only generate one instance per panel. Also, set - * the margins to zero, since they are offset by the enclosing panel. - */ - if (this.hasOwnProperty("index")) { - var s = pv.extend(scene[this.index]); - s.right = s.top = s.left = s.bottom = 0; - return [s]; - } - return scene; -}; - -/** - * @private Returns the first instance of this mark in the scene graph. This - * method can only be called when the mark is bound to the scene graph (for - * example, from an event handler, or within a property function). - * - * @returns a node in the scene graph. - */ -pv.Mark.prototype.first = function() { - return this.scene[0]; -}; - -/** - * @private Returns the last instance of this mark in the scene graph. This - * method can only be called when the mark is bound to the scene graph (for - * example, from an event handler, or within a property function). In addition, - * note that mark instances are built sequentially, so the last instance of this - * mark may not yet be constructed. - * - * @returns a node in the scene graph. - */ -pv.Mark.prototype.last = function() { - return this.scene[this.scene.length - 1]; -}; - -/** - * @private Returns the previous instance of this mark in the scene graph, or - * null if this is the first instance. - * - * @returns a node in the scene graph, or null. - */ -pv.Mark.prototype.sibling = function() { - return (this.index == 0) ? null : this.scene[this.index - 1]; -}; - -/** - * @private Returns the current instance in the scene graph of this mark, in the - * previous instance of the enclosing parent panel. May return null if this - * instance could not be found. - * - * @returns a node in the scene graph, or null. - */ -pv.Mark.prototype.cousin = function() { - var p = this.parent, s = p && p.sibling(); - return (s && s.children) ? s.children[this.childIndex][this.index] : null; -}; - -/** - * Renders this mark, including recursively rendering all child marks if this is - * a panel. This method finds all instances of this mark and renders them. This - * method descends recursively to the level of the mark to be rendered, finding - * all visible instances of the mark. After the marks are rendered, the scene - * and index attributes are removed from the mark to restore them to a clean - * state. - * - *

If an enclosing panel has an index property set (as is the case inside in - * an event handler), then only instances of this mark inside the given instance - * of the panel will be rendered; otherwise, all visible instances of the mark - * will be rendered. - */ -pv.Mark.prototype.render = function() { - /* For the first render, take it from the top. */ - if (this.parent && !this.root.scene) { - this.root.render(); - return; - } - - this.renderCore(); -}; - -pv.Mark.prototype.renderCore = function() { - var parent = this.parent, - stack = pv.Mark.stack; - - /* Record the path to this mark. */ - var indexes = []; - for (var mark = this; mark.parent; mark = mark.parent) { - indexes.unshift(mark.childIndex); - } - - /** @private */ - function render(mark, depth, scale) { - mark.scale = scale; - if (depth < indexes.length) { - stack.unshift(null); - try{ - if (mark.hasOwnProperty("index")) { - renderInstance(mark, depth, scale); - } else { - for (var i = 0, n = mark.scene.length; i < n; i++) { - mark.index = i; - renderInstance(mark, depth, scale); - } - delete mark.index; - } - } finally { - stack.shift(); - } - } else { - mark.build(); - - /* - * In the update phase, the scene is rendered by creating and updating - * elements and attributes in the SVG image. No properties are evaluated - * during the update phase; instead the values computed previously in the - * build phase are simply translated into SVG. The update phase is - * decoupled (see pv.Scene) to allow different rendering engines. - */ - pv.Scene.scale = scale; - - var id = null; // SVGWeb performance enhancement. - if (mark.scene && mark.scene.$g && mark.scene.$g.suspendRedraw) - id = mark.scene.$g.suspendRedraw(1000); - - pv.Scene.updateAll(mark.scene); - - if (id) // SVGWeb performance enhancement. - mark.scene.$g.unsuspendRedraw(id); - } - delete mark.scale; - } - - /** - * @private Recursively renders the current instance of the specified mark. - * This is slightly tricky because `index` and `scene` properties may or may - * not already be set; if they are set, it means we are rendering only a - * specific instance; if they are unset, we are rendering all instances. - * Furthermore, we must preserve the original context of these properties when - * rendering completes. - * - *

Another tricky aspect is that the `scene` attribute should be set for - * any preceding children, so as to allow property chaining. This is - * consistent with first-pass rendering. - */ - function renderInstance(mark, depth, scale) { - var s = mark.scene[mark.index], i; - if (s.visible) { - var childIndex = indexes[depth], - child = mark.children[childIndex]; - - /* Set preceding child scenes. */ - for (i = 0; i < childIndex; i++) { - mark.children[i].scene = s.children[i]; - } - - /* Set current child scene, if necessary. */ - stack[0] = s.data; - if (child.scene) { - render(child, depth + 1, scale * s.transform.k); - } else { - child.scene = s.children[childIndex]; - render(child, depth + 1, scale * s.transform.k); - delete child.scene; - } - - /* Clear preceding child scenes. */ - for (i = 0; i < childIndex; i++) { - delete mark.children[i].scene; - } - } - } - - /* Bind this mark's property definitions. */ - this.bind(); - - /* The render context is the first ancestor with an explicit index. */ - while (parent && !parent.hasOwnProperty("index")) parent = parent.parent; - - /* Recursively render all instances of this mark. */ - this.context( - parent ? parent.scene : undefined, - parent ? parent.index : -1, - function() { render(this.root, 0, 1); }); -}; - -/** - * @private In the bind phase, inherited property definitions are cached so they - * do not need to be queried during build. - */ -pv.Mark.prototype.bind = function() { - var seen = {}, - data, - - /* Required props (no defs) */ - required = [], - - /* - * Optional props/defs by type - * 0 - def/value, - * 1 - def/fun, - * 2 - prop/value, - * 3 - prop/fun - */ - types = [[], [], [], []]; - - /* - * **Evaluation** order (not precedence order for choosing props/defs) - * 0) DEF and PROP _values_ are always already "evaluated". - * * Defined PROPs for which a value/fun was not specified - * get the value null. - * - * 1) DEF _functions_ - * * once per parent instance - * * with parent instance's stack - * - * 1.1) Defaulted - * * from farthest proto mark to closest - * * on each level the first defined is the first evaluated - * - * 1.2) Explicit - * * idem - * - * 2) Data PROP _value_ or _function_ - * * once per all child instances - * * with parent instance's stack - * - * ONCE PER INSTANCE - * - * 3) Required kind PROP _functions_ (id, datum, visible) - * 2.1) Defaulted - * * idem - * 2.2) Explicit - * * idem - * - * 3) Optional kind PROP _functions_ (when instance.visible=true) - * 3.1) Defaulted - * * idem - * 3.2) Explicit - * * idem - * - * 4) Implied PROPs (when instance.visible=true) - */ - /** - * Scans the proto chain for the specified mark. - */ - function bind(mark) { - do { - var properties = mark.$properties; - /* - * On each mark properties are traversed in reverse - * so that, below, when reverse() is called - * function props/defs recover their original defining order. - * - * M1 -> P1_0, P1_1, P1_2, P1_3 - * ^ - * | - * M2 -> P2_0, P2_1 - * ^ - * | - * M3 -> P3_0, P3_1 - * - * List -> P3_1, P3_0, P2_1, P2_0, P1_3, P1_2, P1_1, P1_0 - * - * Reversed -> P1_0, P1_1, P1_2, P1_3, P2_0, P2_1, P3_0, P3_1 - */ - - for (var i = properties.length - 1; i >= 0 ; i--) { - var p = properties[i]; - var pLeaf = seen[p.name]; - if (!pLeaf) { - seen[p.name] = p; - - switch (p.name) { - case "data": - data = p; - break; - - case "visible": - case "id": - required.push(p); - break; - - default: - types[p.type].push(p); - break; - } - } else if(pLeaf.type === 3){ // prop/fun - // Chain properties - // - // seen[name]-> (leaf).proto-> (B).proto-> (C).proto-> (root) - // .root-------------------------------^ - var pRoot = pLeaf.root; - if(!pRoot){ - pLeaf.proto = - pLeaf.root = p; - } else if(!pRoot.proto){ - pRoot.proto = p; - pLeaf.root = p; - } - } - } - } while (mark = mark.proto); - } - - /* Scan the proto chain for all defined properties. */ - bind(this); - bind(this.defaults); - types[1].reverse(); - types[3].reverse(); - - /* Any undefined properties are null. */ - var mark = this; - do { - for (var name in mark.properties) { - if (!(name in seen)) { - types[2].push(seen[name] = {name: name, type: 2, value: null}); - } - } - } while ((mark = mark.proto)); - - /* Define setter-getter for inherited defs. */ - var defs = types[0].concat(types[1]); - for (var i = 0; i < defs.length; i++) { - this.propertyMethod(defs[i].name, true); - } - - /* Setup binds to evaluate constants before functions. */ - this.binds = { - properties: seen, - net: {}, // name -> net index // null = 0 is default position - data: data, - defs: defs, - required: required, - - // NOTE: although defs are included in the optional properties - // they are evaluated once per parent instance, before other non-def properties. - // Yet, for each instance, the already evaluated's def values - // are copied to the instance scene - all instances share the same value... - // Only to satisfy this copy operation they go in the instance-props array. - optional: pv.blend(types) - }; -}; - -pv.Mark.prototype.updateNet = function(pDependent, netIndex){ - var binds = this.binds; - var props = binds.properties; - var net = binds.net; - - propagateRecursive(pDependent, netIndex); - - function propagateRecursive(p, minNetIndex){ - if(minNetIndex > (net[p.name] || 0)){ - net[p.name] = minNetIndex; - var deps = p.dependents; - if(deps){ - minNetIndex++; - for(var depName in deps){ - if(deps.hasOwnProperty(depName)){ - var pDep = props[depName]; - if(pDep){ - propagateRecursive(pDep, minNetIndex); - } - } - } - } - } - } -}; - -/** - * @private Evaluates properties and computes implied properties. Properties are - * stored in the {@link #scene} array for each instance of this mark. - * - *

As marks are built recursively, the {@link #index} property is updated to - * match the current index into the data array for each mark. Note that the - * index property is only set for the mark currently being built and its - * enclosing parent panels. The index property for other marks is unset, but is - * inherited from the global Mark class prototype. This allows mark - * properties to refer to properties on other marks in the same panel - * conveniently; however, in general it is better to reference mark instances - * specifically through the scene graph rather than depending on the magical - * behavior of {@link #index}. - * - *

The root scene array has a special property, data, which stores - * the current data stack. The first element in this stack is the current datum, - * followed by the datum of the enclosing parent panel, and so on. The data - * stack should not be accessed directly; instead, property functions are passed - * the current data stack as arguments. - * - *

The evaluation of the data and visible properties is - * special. The data property is evaluated first; unlike the other - * properties, the data stack is from the parent panel, rather than the current - * mark, since the data is not defined until the data property is evaluated. - * The visible property is subsequently evaluated for each instance; - * only if true will the {@link #buildInstance} method be called, evaluating - * other properties and recursively building the scene graph. - * - *

If this mark is being re-built, any old instances of this mark that no - * longer exist (because the new data array contains fewer elements) will be - * cleared using {@link #clearInstance}. - * - * @param parent the instance of the parent panel from the scene graph. - */ -pv.Mark.prototype.build = function() { - var scene = this.scene, stack = pv.Mark.stack; - if (!scene) { - scene = this.scene = []; - scene.mark = this; - scene.type = this.type; - scene.childIndex = this.childIndex; - if (this.parent) { - scene.parent = this.parent.scene; - scene.parentIndex = this.parent.index; - } - } - - /* Resolve anchor target. */ - if (this.target) scene.target = this.target.instances(scene); - - /* Evaluate defs. */ - if (this.binds.defs.length) { - var defs = scene.defs; - if (!defs) scene.defs = defs = {}; - for (var i = 0; i < this.binds.defs.length; i++) { - var p = this.binds.defs[i], d = defs[p.name]; - if (!d || (p.id > d.id)) { - defs[p.name] = { - id: 0, // this def will be re-evaluated on next build - value: (p.type & 1) ? p.value.apply(this, stack) : p.value - }; - } - } - } - - /* Evaluate special data property. */ - var data = this.binds.data; - data = data.type & 1 ? data.value.apply(this, stack) : data.value; - - /* Create, update and delete scene nodes. */ - var markProto = pv.Mark.prototype; - stack.unshift(null); - try { - /* Adjust scene length to data length. */ - var L = scene.length = data.length; - for (var i = 0 ; i < L ; i++) { - markProto.index = this.index = i; - - var s = scene[i] || (scene[i] = {}); - - /* Fill special data property and update the stack. */ - s.data = stack[0] = data[i]; - - this.buildInstance(s); - } - } finally { - markProto.index = -1; - delete this.index; - stack.shift(); - } - - return this; -}; - -/** - * @private Evaluates the specified array of properties for the specified - * instance s in the scene graph. - * - * @param s a node in the scene graph; the instance of the mark to build. - * @param properties an array of properties. - */ -pv.Mark.prototype.buildProperties = function(s, properties) { - var stack = pv.Mark.stack; - for (var i = 0, n = properties.length; i < n; i++) { - var p = properties[i]; - - // repeated here, for performance - var v; - switch(p.type){ - /* 2 most common first */ - case 3: - var oldProtoProp = pv.propertyProto; - try{ - pv.propertyProto = p.proto; - v = p.value.apply(this, stack); - } finally { - pv.propertyProto = oldProtoProp; - } - break; - - case 2: - v = p.value; - break; - - // copy already evaluated def value to each instance's scene - case 0: - case 1: - v = this.scene.defs[p.name].value; - break; - } - - s[p.name] = v; - } -}; - -pv.Mark.prototype.delegate = function(dv, tag){ - var protoProp = pv.propertyProto; - if(protoProp && (!tag || protoProp.tag === tag)){ - var value = this.evalProperty(protoProp); - if(value !== undefined){ - return value; - } - } - - return dv; -}; - -pv.Mark.prototype.hasDelegate = function(tag){ - var protoProp = pv.propertyProto; - return !!protoProp && (!tag || protoProp.tag === tag); -}; - -pv.Mark.prototype.evalProperty = function(p){ - switch(p.type){ - /* 2 most common first */ - case 3: - var oldProtoProp = pv.propertyProto; - try{ - pv.propertyProto = p.proto; - return p.value.apply(this, pv.Mark.stack); - } finally { - pv.propertyProto = oldProtoProp; - } - - case 2: return p.value; - - // copy already evaluated def value to each instance's scene - case 0: - case 1: return this.scene.defs[p.name].value; - } -}; - -pv.Mark.prototype.buildPropertiesWithDepTracking = function(s, properties) { - // Current bindings - var net = this.binds.net; - var netIndex, newNetIndex, netDirtyProps, prevNetDirtyProps, - propertyIndexes, evaluatedProps; - var stack = pv.Mark.stack; - - var n = properties.length; - try{ - while(true){ - netDirtyProps = null; - evaluatedProps = {}; - for (var i = 0 ; i < n; i++) { - var p = properties[i]; - var name = p.name; - evaluatedProps[name] = true; - - // Only re-evaluate properties marked dirty on the previous iteration - if(!prevNetDirtyProps || prevNetDirtyProps[name]){ - var v; - switch (p.type) { - case 3: - pv.propertyEval = p; - pv.propertyEvalNetIndex = netIndex = (net[name] || 0); - pv.propertyEvalDependencies = null; - - // repeated here, for performance - var oldProtoProp = pv.propertyProto; - try{ - pv.propertyProto = p.proto; - v = p.value.apply(this, stack); - } finally { - pv.propertyProto = oldProtoProp; - } - - newNetIndex = pv.propertyEvalNetIndex; - if(newNetIndex > netIndex){ - var evalDeps = pv.propertyEvalDependencies; - for(var depName in evalDeps){ - // If dependent property has not yet been evaluated - // set it as dirty - if(evalDeps.hasOwnProperty(depName) && - !evaluatedProps.hasOwnProperty(name)){ - if(!netDirtyProps){ - netDirtyProps = {}; - } - netDirtyProps[depName] = true; - } - } - - this.updateNet(p, newNetIndex); - } - break; - - case 2: - v = p.value; - break; - - // copy already evaluated def value to each instance's scene - case 0: - case 1: - v = this.scene.defs[name].value; - break; - } - - s[name] = v; - } - } - - if(!netDirtyProps){ - break; - } - - prevNetDirtyProps = netDirtyProps; - - // Sort properties on net index and repeat... - - propertyIndexes = pv.numerate(properties, function(p){ return p.name; }); - - properties.sort(function(pa, pb){ - var comp = pv.naturalOrder(net[pa.name] || 0, net[pb.name] || 0); - if(!comp){ - // Force mantaining original order - comp = pv.naturalOrder(propertyIndexes[pa.name], propertyIndexes[pb.name]); - } - return comp; - }); - - propertyIndexes = null; - } - } finally { - pv.propertyEval = null; - pv.propertyEvalNetIndex = null; - pv.propertyEvalDependencies = null; - } -}; - -/** - * @private Evaluates all of the properties for this mark for the specified - * instance s in the scene graph. The set of properties to evaluate is - * retrieved from the {@link #properties} array for this mark type (see {@link - * #type}). After these properties are evaluated, any implied properties - * may be computed by the mark and set on the scene graph; see - * {@link #buildImplied}. - * - *

For panels, this method recursively builds the scene graph for all child - * marks as well. In general, this method should not need to be overridden by - * concrete mark types. - * - * @param s a node in the scene graph; the instance of the mark to build. - */ -pv.Mark.prototype.buildInstance = function(s) { - this.buildProperties(s, this.binds.required); - if (s.visible) { - if(this.index === 0){ - this.buildPropertiesWithDepTracking(s, this.binds.optional); - } else { - this.buildProperties(s, this.binds.optional); - } - - this.buildImplied(s); - } -}; - -/** - * @private Computes the implied properties for this mark for the specified - * instance s in the scene graph. Implied properties are those with - * dependencies on multiple other properties; for example, the width property - * may be implied if the left and right properties are set. This method can be - * overridden by concrete mark types to define new implied properties, if - * necessary. - * - * @param s a node in the scene graph; the instance of the mark to build. - */ -pv.Mark.prototype.buildImplied = function(s) { - var l = s.left; - var r = s.right; - var t = s.top; - var b = s.bottom; - - /* Assume width and height are zero if not supported by this mark type. */ - var p = this.properties; - var w = p.width ? s.width : 0; - var h = p.height ? s.height : 0; - - /* Compute implied width, right and left. */ - var instance; - var checked; - - if(w == null || r == null || l == null){ - instance = this.parent ? this.parent.instance() : null; - checked = true; - var width = instance ? instance.width : (w + l + r); - if (w == null) { - w = width - (r = r || 0) - (l = l || 0); - } else if (r == null) { - if (l == null) { - l = r = (width - w) / 2; - } else { - r = width - w - l; - } - } else { - l = width - w - r; - } - } - - /* Compute implied height, bottom and top. */ - if (h == null || b == null || t == null) { - if(!checked){ - instance = this.parent ? this.parent.instance() : null; - } - - var height = instance ? instance.height : (h + t + b); - if (h == null) { - h = height - (t = t || 0) - (b = b || 0); - } else if (b == null) { - if (t == null) { - b = t = (height - h) / 2; - } else { - b = height - h - t; - } - } else { - t = height - h - b; - } - } - - s.left = l; - s.right = r; - s.top = t; - s.bottom = b; - - /* Only set width and height if they are supported by this mark type. */ - if (p.width ) s.width = w; - if (p.height) s.height = h; - - /* Set any null colors to pv.FillStyle.transparent. */ - if (p.textStyle && !s.textStyle ) s.textStyle = pv.FillStyle.transparent; - if (p.fillStyle && !s.fillStyle ) s.fillStyle = pv.FillStyle.transparent; - if (p.strokeStyle && !s.strokeStyle) s.strokeStyle = pv.FillStyle.transparent; -}; - -/** - * Returns the current location of the mouse (cursor) relative to this mark's - * parent. The x coordinate corresponds to the left margin, while the - * y coordinate corresponds to the top margin. - * - * @returns {pv.Vector} the mouse location. - */ -pv.Mark.prototype.mouse = function() { - var n = this.root.canvas(), - ev = pv.event, - x = ev.pageX, - y = ev.pageY; - - // Compute xy-coordinates relative to the panel. - var offset = pv.elementOffset(n); - if(offset){ - x -= offset.left; - y -= offset.top; - - var computed = pv.getWindow(n.ownerDocument).getComputedStyle(n, null); - if(computed){ - x -= parseFloat(computed.paddingLeft || 0); - y -= parseFloat(computed.paddingTop || 0); - } - } - - /* Compute the inverse transform of all enclosing panels. */ - var t = pv.Transform.identity, - p = this.properties.transform ? this : this.parent, - pz = []; - - do { - pz.push(p); - } while ((p = p.parent)); - - while ((p = pz.pop())) { - var pinst = p.instance(); - t = t.translate(pinst.left, pinst.top) - .times(pinst.transform); - } - - t = t.invert(); - return pv.vector(x * t.k + t.x, y * t.k + t.y); -}; - -/** - * Registers an event handler for the specified event type with this mark. When - * an event of the specified type is triggered, the specified handler will be - * invoked. The handler is invoked in a similar method to property functions: - * the context is this mark instance, and the arguments are the full - * data stack. Event handlers can use property methods to manipulate the display - * properties of the mark: - * - *

m.event("click", function() this.fillStyle("red"));
- * - * Alternatively, the external data can be manipulated and the visualization - * redrawn: - * - *
m.event("click", function(d) {
- *     data = all.filter(function(k) k.name == d);
- *     vis.render();
- *   });
- * - * The return value of the event handler determines which mark gets re-rendered. - * Use defs ({@link #def}) to set temporary state from event handlers. - * - *

The complete set of event types is defined by SVG; see the reference - * below. The set of supported event types is:

    - * - *
  • click - *
  • mousedown - *
  • mouseup - *
  • mouseover - *
  • mousemove - *
  • mouseout - * - *
Since Protovis does not specify any concept of focus, it does not - * support key events; these should be handled outside the visualization using - * standard JavaScript. In the future, support for interaction may be extended - * to support additional event types, particularly those most relevant to - * interactive visualization, such as selection. - * - *

TODO In the current implementation, event handlers are not inherited from - * prototype marks. They must be defined explicitly on each interactive mark. - * More than one event handler for a given event type can be defined. - * The return values of each handler, if any and are marks, - * are rendered at the end of every handler having been called. - * - * @see SVG events - * @param {string} type the event type. - * @param {function} handler the event handler. - * @returns {pv.Mark} this. - */ -pv.Mark.prototype.event = function(type, handler) { - handler = pv.functor(handler); - - var handlers = this.$handlers[type]; - if(!handlers) { - handlers = handler; - } else if(handlers instanceof Array) { - handlers.push(handler); - } else { - handlers = [handlers, handler]; - } - - this.$hasHandlers = true; - this.$handlers[type] = handlers; - return this; -}; - -/** @private Evaluates the function f with the specified context. */ -pv.Mark.prototype.context = function(scene, index, f) { - var proto = pv.Mark.prototype, - stack = pv.Mark.stack, - oscene = pv.Mark.scene, - oindex = proto.index; - - /** @private Sets the context. */ - function apply(scene, index) { - pv.Mark.scene = scene; - proto.index = index; - if (!scene) { - return; - } - - var that = scene.mark, - mark = that, - ancestors = []; - - /* Set ancestors' scene and index; populate data stack. */ - do { - ancestors.push(mark); - stack.push(scene[index].data); - - mark.index = index; - mark.scene = scene; - - index = scene.parentIndex; - scene = scene.parent; - } while (mark = mark.parent); - - /* Set ancestors' scale; requires top-down. */ - for (var i = ancestors.length - 1, k = 1; i > 0; i--) { - mark = ancestors[i]; - mark.scale = k; - k *= mark.scene[mark.index].transform.k; - } - - /* Set direct children of "that"'s scene and scale. */ - var children = that.children; - if (children){ - var thatInstance = that.scene[that.index]; - for (var i = 0, n = children.length ; i < n; i++) { - mark = children[i]; - mark.scene = thatInstance.children[i]; - mark.scale = k; - } - } - } - - /** @private Clears the context. */ - function clear(scene, index) { - if (!scene) return; - var that = scene.mark, - mark; - - /* Reset children. */ - var children = that.children; - if (children){ - for (var i = 0, n = children.length ; i < n; i++) { - mark = children[i]; - delete mark.scene; - delete mark.scale; - } - } - - /* Reset ancestors. */ - mark = that; - do { - stack.pop(); - if (mark.parent) { - delete mark.scene; - delete mark.scale; - } - delete mark.index; - } while (mark = mark.parent); - } - - /* Context switch, invoke the function, then switch back. */ - if(scene && scene === oscene && index === oindex){ - // already there - try{ - f.apply(this, stack); - } catch (ex) { - pv.error(ex); - throw ex; - } finally { - // Some guys like setting index to -1... - pv.Mark.scene = oscene; - proto.index = oindex; - } - } else { - clear(oscene, oindex); - apply(scene, index); - try { - f.apply(this, stack); - } catch (ex) { - pv.error(ex); - throw ex; - } finally { - clear(scene, index); - apply(oscene, oindex); - } - } -}; - -pv.Mark.getEventHandler = function(type, scenes, index, event){ - var handler = scenes.mark.$handlers[type]; - if(handler){ - return [handler, type, scenes, index, event]; - } - - var parentScenes = scenes.parent; - if(parentScenes){ - return this.getEventHandler(type, parentScenes, scenes.parentIndex, event); - } -}; - -/** @private Execute the event listener, then re-render the returned mark. */ -pv.Mark.dispatch = function(type, scenes, index, event) { - - var root = scenes.mark.root; - if(root.animatingCount){ - return true; - } - - var handlerInfo; - var interceptors = root.$interceptors && root.$interceptors[type]; - if(interceptors){ - for(var i = 0, L = interceptors.length ; i < L ; i++){ - handlerInfo = interceptors[i](type, event); - if(handlerInfo){ - break; - } - - if(handlerInfo === false){ - // Consider handled - return true; - } - } - } - - if(!handlerInfo){ - handlerInfo = this.getEventHandler(type, scenes, index, event); - } - - return handlerInfo ? this.handle.apply(this, handlerInfo) : false; -}; - -pv.Mark.handle = function(handler, type, scenes, index, event){ - var m = scenes.mark; - - m.context(scenes, index, function() { - var stack = pv.Mark.stack.concat(event); - if(handler instanceof Array) { - var ms; - handler.forEach(function(hi){ - var mi = hi.apply(m, stack); - if(mi && mi.render) { - (ms || (ms = [])).push(mi); - } - }); - - if(ms) { ms.forEach(function(mi){ mi.render(); }); } - } else { - m = handler.apply(m, stack); - if (m && m.render) { - m.render(); - } - } - }); - - return true; -}; - -/** - * Registers an event interceptor function. - * - * @param {string} type the event type - * @param {function} handler the interceptor function - * @param {boolean} [before=false] indicates that the interceptor should be applied before "after" interceptors - */ -pv.Mark.prototype.addEventInterceptor = function(type, handler, before){ - var root = this.root; - if(root){ - var interceptors = root.$interceptors || (root.$interceptors = {}); - var list = interceptors[type] || (interceptors[type] = []); - if(before){ - list.unshift(handler); - } else { - list.push(handler); - } - } -}; - -/** - * Iterates through all visible instances that - * this mark has rendered. - */ -pv.Mark.prototype.eachInstance = function(fun, ctx){ - var mark = this, - indexes = []; - - /* Go up to the root and register our way back. - * The root mark never "looses" its scene. - */ - while(mark.parent){ - indexes.unshift(mark.childIndex); - mark = mark.parent; - } - - // mark != null - - // root scene exists if rendered at least once - var rootScene = mark.scene; - if(!rootScene){ - return; - } - - var L = indexes.length; - - function mapRecursive(scene, level, toScreen){ - var D = scene.length; - if(D > 0){ - var isLastLevel = level === L, - childIndex; - - if(!isLastLevel) { - childIndex = indexes[level]; - } - - for(var index = 0 ; index < D ; index++){ - var instance = scene[index]; - if(instance.visible){ - if(level === L){ - fun.call(ctx, scene, index, toScreen); - } else { - var childScene = instance.children[childIndex]; - if(childScene){ // Some nodes might have not been rendered??? - var childToScreen = toScreen - .times(instance.transform) - .translate(instance.left, instance.top); - - mapRecursive(childScene, level + 1, childToScreen); - } - } - } - } - } - } - - mapRecursive(rootScene, 0, pv.Transform.identity); -}; - -pv.Mark.prototype.toScreenTransform = function(){ - var t = pv.Transform.identity; - - if(this instanceof pv.Panel) { - t = t.translate(this.left(), this.top()) - .times(this.transform()); - } - - var parent = this.parent; // TODO : this.properties.transform ? this : this.parent - if(parent){ - do { - t = t.translate(parent.left(), parent.top()) - .times(parent.transform()); - } while((parent = parent.parent)); - } - - return t; -}; - -pv.Mark.prototype.transition = function() { - return new pv.Transition(this); -}; - -pv.Mark.prototype.on = function(state) { - return this["$" + state] = new pv.Transient(this); -}; - -// -------------- - -pv.Mark.prototype.getShape = function(scenes, index){ - var s = scenes[index]; - if(!s.visible){ - return null; - } - - return s._shape || (s._shape = this.getShapeCore(scenes, index)); -}; - -pv.Mark.prototype.getShapeCore = function(scenes, index){ - var s = scenes[index]; - return new pv.Shape.Rect(s.left, s.top, s.width, s.height); -}; -/** - * Constructs a new mark anchor with default properties. - * - * @class Represents an anchor on a given mark. An anchor is itself a mark, but - * without a visual representation. It serves only to provide useful default - * properties that can be inherited by other marks. Each type of mark can define - * any number of named anchors for convenience. If the concrete mark type does - * not define an anchor implementation specifically, one will be inherited from - * the mark's parent class. - * - *

For example, the bar mark provides anchors for its four sides: left, - * right, top and bottom. Adding a label to the top anchor of a bar, - * - *

bar.anchor("top").add(pv.Label);
- * - * will render a text label on the top edge of the bar; the top anchor defines - * the appropriate position properties (top and left), as well as text-rendering - * properties for convenience (textAlign and textBaseline). - * - *

Note that anchors do not inherit from their targets; the positional - * properties are copied from the scene graph, which guarantees that the anchors - * are positioned correctly, even if the positional properties are not defined - * deterministically. (In addition, it also improves performance by avoiding - * re-evaluating expensive properties.) If you want the anchor to inherit from - * the target, use {@link pv.Mark#extend} before adding. For example: - * - *

bar.anchor("top").extend(bar).add(pv.Label);
- * - * The anchor defines it's own positional properties, but other properties (such - * as the title property, say) can be inherited using the above idiom. Also note - * that you can override positional properties in the anchor for custom - * behavior. - * - * @extends pv.Mark - * @param {pv.Mark} target the anchor target. - */ -pv.Anchor = function(target) { - pv.Mark.call(this); - this.target = target; - this.parent = target.parent; -}; - -pv.Anchor.prototype = pv.extend(pv.Mark) - .property("name", String); - -/** - * The anchor name. The set of supported anchor names is dependent on the - * concrete mark type; see the mark type for details. For example, bars support - * left, right, top and bottom anchors. - * - *

While anchor names are typically constants, the anchor name is a true - * property, which means you can specify a function to compute the anchor name - * dynamically. For instance, if you wanted to alternate top and bottom anchors, - * saying - * - *

m.anchor(function() (this.index % 2) ? "top" : "bottom").add(pv.Dot);
- * - * would have the desired effect. - * - * @type string - * @name pv.Anchor.prototype.name - */ - -/** - * Sets the prototype of this anchor to the specified mark. Any properties not - * defined on this mark may be inherited from the specified prototype mark, or - * its prototype, and so on. The prototype mark need not be the same type of - * mark as this mark. (Note that for inheritance to be useful, properties with - * the same name on different mark types should have equivalent meaning.) - * - *

This method differs slightly from the normal mark behavior in that the - * anchor's target is preserved. - * - * @param {pv.Mark} proto the new prototype. - * @returns {pv.Anchor} this anchor. - * @see pv.Mark#add - */ -pv.Anchor.prototype.extend = function(proto) { - this.proto = proto; - return this; -}; -/** - * Constructs a new area mark with default properties. Areas are not typically - * constructed directly, but by adding to a panel or an existing mark via - * {@link pv.Mark#add}. - * - * @class Represents an area mark: the solid area between two series of - * connected line segments. Unsurprisingly, areas are used most frequently for - * area charts. - * - *

Just as a line represents a polyline, the Area mark type - * represents a polygon. However, an area is not an arbitrary polygon; - * vertices are paired either horizontally or vertically into parallel - * spans, and each span corresponds to an associated datum. Either the - * width or the height must be specified, but not both; this determines whether - * the area is horizontally-oriented or vertically-oriented. Like lines, areas - * can be stroked and filled with arbitrary colors. - * - *

See also the Area guide. - * - * @extends pv.Mark - */ -pv.Area = function() { - pv.Mark.call(this); -}; - -pv.Area.castSegmented = function(v){ - if(!v){ - return ''; - } - - switch(v){ - case 'smart': - case 'full': - break; - - default: - v = 'full'; - } - - return v; -}; - -pv.Area.prototype = pv.extend(pv.Mark) - .property("width", Number) - .property("height", Number) - .property("lineWidth", Number) - .property("lineJoin", String) - .property("strokeMiterLimit", Number) - .property("lineCap", String) - .property("strokeDasharray", String) - .property("strokeStyle", pv.fillStyle) - .property("fillStyle", pv.fillStyle) - .property("segmented", pv.Area.castSegmented) - .property("interpolate", String) - .property("tension", Number); - -pv.Area.prototype.type = "area"; - -/** - * The width of a given span, in pixels; used for horizontal spans. If the width - * is specified, the height property should be 0 (the default). Either the top - * or bottom property should be used to space the spans vertically, typically as - * a multiple of the index. - * - * @type number - * @name pv.Area.prototype.width - */ - -/** - * The height of a given span, in pixels; used for vertical spans. If the height - * is specified, the width property should be 0 (the default). Either the left - * or right property should be used to space the spans horizontally, typically - * as a multiple of the index. - * - * @type number - * @name pv.Area.prototype.height - */ - -/** - * The width of stroked lines, in pixels; used in conjunction with - * strokeStyle to stroke the perimeter of the area. Unlike the - * {@link Line} mark type, the entire perimeter is stroked, rather than just one - * edge. The default value of this property is 1.5, but since the default stroke - * style is null, area marks are not stroked by default. - * - *

This property is fixed for non-segmented areas. See - * {@link pv.Mark}. - * - * @type number - * @name pv.Area.prototype.lineWidth - */ - -/** - * The style of stroked lines; used in conjunction with lineWidth to - * stroke the perimeter of the area. Unlike the {@link Line} mark type, the - * entire perimeter is stroked, rather than just one edge. The default value of - * this property is null, meaning areas are not stroked by default. - * - *

This property is fixed for non-segmented areas. See - * {@link pv.Mark}. - * - * @type string - * @name pv.Area.prototype.strokeStyle - * @see pv.color - */ - -/** - * The area fill style; if non-null, the interior of the polygon forming the - * area is filled with the specified color. The default value of this property - * is a categorical color. - * - *

This property is fixed for non-segmented areas. See - * {@link pv.Mark}. - * - * @type string - * @name pv.Area.prototype.fillStyle - * @see pv.color - */ - -/** - * Whether the area is segmented; whether variations in fill style, stroke - * style, and the other properties are treated as fixed. Rendering segmented - * areas is noticeably slower than non-segmented areas. - * - *

This property is fixed. See {@link pv.Mark}. - * - * @type boolean - * @name pv.Area.prototype.segmented - */ - -/** - * How to interpolate between values. Linear interpolation ("linear") is the - * default, producing a straight line between points. For piecewise constant - * functions (i.e., step functions), either "step-before" or "step-after" can be - * specified. To draw open uniform b-splines, specify "basis". To draw cardinal - * splines, specify "cardinal"; see also {@link #tension}. - * - *

This property is fixed. See {@link pv.Mark}. - * - * @type string - * @name pv.Area.prototype.interpolate - */ - -/** - * The tension of cardinal splines; used in conjunction with - * interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with - * the given tension. In some sense, the tension can be interpreted as the - * "length" of the tangent; a tension of 1 will yield all zero tangents (i.e., - * linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The - * default value is 0.7. - * - *

This property is fixed. See {@link pv.Mark}. - * - * @type number - * @name pv.Area.prototype.tension - */ - -/** - * Default properties for areas. By default, there is no stroke and the fill - * style is a categorical color. - * - * @type pv.Area - */ -pv.Area.prototype.defaults = new pv.Area() - .extend(pv.Mark.prototype.defaults) - .lineWidth(1.5) - .fillStyle(pv.Colors.category20().by(pv.parent)) - .interpolate("linear") - .tension(.7) - .lineJoin("miter") - .strokeMiterLimit(8) - .lineCap("butt") - .strokeDasharray("none"); - -/** @private Sets width and height to zero if null. */ -pv.Area.prototype.buildImplied = function(s) { - if (s.height == null) s.height = 0; - if (s.width == null) s.width = 0; - pv.Mark.prototype.buildImplied.call(this, s); -}; - -/** @private Records which properties may be fixed. */ -pv.Area.fixed = { - lineWidth: 1, - lineJoin: 1, - strokeMiterLimit: 1, - lineCap: 1, - strokeStyle: 1, - strokeDasharray: 1, - fillStyle: 1, - segmented: 1, - interpolate: 1, - tension: 1 -}; - -/** - * @private Make segmented required, such that this fixed property is always - * evaluated, even if the first segment is not visible. Also cache which - * properties are normally fixed. - */ -pv.Area.prototype.bind = function() { - pv.Mark.prototype.bind.call(this); - var binds = this.binds, - required = binds.required, - optional = binds.optional; - for (var i = 0, n = optional.length; i < n; i++) { - var p = optional[i]; - p.fixed = p.name in pv.Area.fixed; - if (p.name == "segmented") { - required.push(p); - optional.splice(i, 1); - i--; - n--; - } - } - - /* Cache the original arrays so they can be restored on build. */ - this.binds.$required = required; - this.binds.$optional = optional; -}; - -/** - * @private Override the default build behavior such that fixed properties are - * determined dynamically, based on the value of the (always) fixed segmented - * property. Any fixed properties are only evaluated on the first instance, - * although their values are propagated to subsequent instances, so that they - * are available for property chaining and the like. - */ -pv.Area.prototype.buildInstance = function(s) { - var binds = this.binds; - - /* Handle fixed properties on secondary instances. */ - if (this.index) { - var fixed = binds.fixed; - - /* Determine which properties are fixed. */ - if (!fixed) { - fixed = binds.fixed = []; - - function f(p) { return !p.fixed || (fixed.push(p), false); } - - binds.required = binds.required.filter(f); - if (!this.scene[0].segmented) binds.optional = binds.optional.filter(f); - } - - /* Copy fixed property values from the first instance. */ - var n = fixed.length; - if(n){ - var firstScene = this.scene[0]; - for (var i = 0 ; i < n ; i++) { - var p = fixed[i].name; - s[p] = firstScene[p]; - } - } - } - - /* Evaluate all properties on the first instance. */ - else { - binds.required = binds.$required; - binds.optional = binds.$optional; - binds.fixed = null; - } - - pv.Mark.prototype.buildInstance.call(this, s); -}; - -/** - * Constructs a new area anchor with default properties. Areas support five - * different anchors:

    - * - *
  • top - *
  • left - *
  • center - *
  • bottom - *
  • right - * - *
In addition to positioning properties (left, right, top bottom), the - * anchors support text rendering properties (text-align, text-baseline). Text - * is rendered to appear inside the area. The area anchor also propagates the - * interpolate, eccentricity, and tension properties such that an anchored area - * or line will match positions between control points. - * - *

For consistency with the other mark types, the anchor positions are - * defined in terms of their opposite edge. For example, the top anchor defines - * the bottom property, such that an area added to the top anchor grows upward. - * - * @param {string} name the anchor name; either a string or a property function. - * @returns {pv.Anchor} - */ -pv.Area.prototype.anchor = function(name) { - var scene; - return pv.Mark.prototype.anchor.call(this, name) - .interpolate(function() { - return this.scene.target[this.index].interpolate; - }) - .eccentricity(function() { - return this.scene.target[this.index].eccentricity; - }) - .tension(function() { - return this.scene.target[this.index].tension; - }); -}; - - -pv.Area.prototype.getShapeCore = function(scenes, index){ - var s = scenes[index]; - var w = (s.width || 0), - h = (s.height || 0), - x = s.left, - y = s.top; - - var s2 = index + 1 < scenes.length ? scenes[index + 1] : null; - if(!s2 || !s2.visible){ - return new pv.Shape.Line(x, y, x + w, y + h); - } - - var x2 = s2.left, - y2 = s2.top, - h2 = s2.height || 0, - w2 = s2.width || 0; - - return new pv.Shape.Polygon([ - new pv.Vector(x, y ), - new pv.Vector(x2, y2 ), - new pv.Vector(x2 + w2, y2 + h2), - new pv.Vector(x + w, y + h ) - ]); -}; -/** - * Constructs a new bar mark with default properties. Bars are not typically - * constructed directly, but by adding to a panel or an existing mark via - * {@link pv.Mark#add}. - * - * @class Represents a bar: an axis-aligned rectangle that can be stroked and - * filled. Bars are used for many chart types, including bar charts, histograms - * and Gantt charts. Bars can also be used as decorations, for example to draw a - * frame border around a panel; in fact, a panel is a special type (a subclass) - * of bar. - * - *

Bars can be positioned in several ways. Most commonly, one of the four - * corners is fixed using two margins, and then the width and height properties - * determine the extent of the bar relative to this fixed location. For example, - * using the bottom and left properties fixes the bottom-left corner; the width - * then extends to the right, while the height extends to the top. As an - * alternative to the four corners, a bar can be positioned exclusively using - * margins; this is convenient as an inset from the containing panel, for - * example. See {@link pv.Mark} for details on the prioritization of redundant - * positioning properties. - * - *

See also the Bar guide. - * - * @extends pv.Mark - */ -pv.Bar = function() { - pv.Mark.call(this); -}; - -pv.Bar.prototype = pv.extend(pv.Mark) - .property("width", Number) - .property("height", Number) - .property("lineWidth", Number) - .property("strokeStyle", pv.fillStyle) - .property("fillStyle", pv.fillStyle) - .property("lineCap", String) - .property("strokeDasharray", String); - -pv.Bar.prototype.type = "bar"; - -/** - * The width of the bar, in pixels. If the left position is specified, the bar - * extends rightward from the left edge; if the right position is specified, the - * bar extends leftward from the right edge. - * - * @type number - * @name pv.Bar.prototype.width - */ - -/** - * The height of the bar, in pixels. If the bottom position is specified, the - * bar extends upward from the bottom edge; if the top position is specified, - * the bar extends downward from the top edge. - * - * @type number - * @name pv.Bar.prototype.height - */ - -/** - * The width of stroked lines, in pixels; used in conjunction with - * strokeStyle to stroke the bar's border. - * - * @type number - * @name pv.Bar.prototype.lineWidth - */ - -/** - * The style of stroked lines; used in conjunction with lineWidth to - * stroke the bar's border. The default value of this property is null, meaning - * bars are not stroked by default. - * - * @type string - * @name pv.Bar.prototype.strokeStyle - * @see pv.color - */ - -/** - * The bar fill style; if non-null, the interior of the bar is filled with the - * specified color. The default value of this property is a categorical color. - * - * @type string - * @name pv.Bar.prototype.fillStyle - * @see pv.color - */ - -/** - * Default properties for bars. By default, there is no stroke and the fill - * style is a categorical color. - * - * @type pv.Bar - */ -pv.Bar.prototype.defaults = new pv.Bar() - .extend(pv.Mark.prototype.defaults) - .lineWidth(1.5) - .fillStyle(pv.Colors.category20().by(pv.parent)) - .lineCap("butt") - .strokeDasharray("none"); -/** - * Constructs a new dot mark with default properties. Dots are not typically - * constructed directly, but by adding to a panel or an existing mark via - * {@link pv.Mark#add}. - * - * @class Represents a dot; a dot is simply a sized glyph centered at a given - * point that can also be stroked and filled. The size property is - * proportional to the area of the rendered glyph to encourage meaningful visual - * encodings. Dots can visually encode up to eight dimensions of data, though - * this may be unwise due to integrality. See {@link pv.Mark} for details on the - * prioritization of redundant positioning properties. - * - *

See also the Dot guide. - * - * @extends pv.Mark - */ -pv.Dot = function() { - pv.Mark.call(this); -}; - -pv.Dot.prototype = pv.extend(pv.Mark) - .property("shape", String) - .property("shapeAngle", Number) - .property("shapeRadius", Number) - .property("shapeSize", Number) - .property("lineWidth", Number) - .property("strokeStyle", pv.fillStyle) - .property("lineCap", String) - .property("strokeDasharray", String) - .property("fillStyle", pv.fillStyle); - -pv.Dot.prototype.type = "dot"; - -/** - * The size of the shape, in square pixels. Square pixels are used such that the - * area of the shape is linearly proportional to the value of the - * shapeSize property, facilitating representative encodings. This is - * an alternative to using {@link #shapeRadius}. - * - * @see #shapeRadius - * @type number - * @name pv.Dot.prototype.shapeSize - */ - -/** - * The radius of the shape, in pixels. This is an alternative to using - * {@link #shapeSize}. - * - * @see #shapeSize - * @type number - * @name pv.Dot.prototype.shapeRadius - */ - -/** - * The shape name. Several shapes are supported:

    - * - *
  • cross - *
  • triangle - *
  • diamond - *
  • square - *
  • circle - *
  • tick - *
  • bar - * - *
These shapes can be further changed using the {@link #angle} property; - * for instance, a cross can be turned into a plus by rotating. Similarly, the - * tick, which is vertical by default, can be rotated horizontally. Note that - * some shapes (cross and tick) do not have interior areas, and thus do not - * support fill style meaningfully. - * - *

Note: it may be more natural to use the {@link pv.Rule} mark for - * horizontal and vertical ticks. The tick shape is only necessary if angled - * ticks are needed. - * - * @type string - * @name pv.Dot.prototype.shape - */ - -/** - * The shape rotation angle, in radians. Used to rotate shapes, such as to turn - * a cross into a plus. - * - * @type number - * @name pv.Dot.prototype.shapeAngle - */ - -/** - * The width of stroked lines, in pixels; used in conjunction with - * strokeStyle to stroke the dot's shape. - * - * @type number - * @name pv.Dot.prototype.lineWidth - */ - -/** - * The style of stroked lines; used in conjunction with lineWidth to - * stroke the dot's shape. The default value of this property is a categorical - * color. - * - * @type string - * @name pv.Dot.prototype.strokeStyle - * @see pv.color - */ - -/** - * The fill style; if non-null, the interior of the dot is filled with the - * specified color. The default value of this property is null, meaning dots are - * not filled by default. - * - * @type string - * @name pv.Dot.prototype.fillStyle - * @see pv.color - */ - -/** - * Default properties for dots. By default, there is no fill and the stroke - * style is a categorical color. The default shape is "circle" with radius 4.5. - * - * @type pv.Dot - */ -pv.Dot.prototype.defaults = new pv.Dot() - .extend(pv.Mark.prototype.defaults) - .shape("circle") - .lineWidth(1.5) - .strokeStyle(pv.Colors.category10().by(pv.parent)) - .lineCap("butt") - .strokeDasharray("none"); - -/** - * Constructs a new dot anchor with default properties. Dots support five - * different anchors:

    - * - *
  • top - *
  • left - *
  • center - *
  • bottom - *
  • right - * - *
In addition to positioning properties (left, right, top bottom), the - * anchors support text rendering properties (text-align, text-baseline). Text is - * rendered to appear outside the dot. Note that this behavior is different from - * other mark anchors, which default to rendering text inside the mark. - * - *

For consistency with the other mark types, the anchor positions are - * defined in terms of their opposite edge. For example, the top anchor defines - * the bottom property, such that a bar added to the top anchor grows upward. - * - * @param {string} name the anchor name; either a string or a property function. - * @returns {pv.Anchor} - */ -pv.Dot.prototype.anchor = function(name) { - var scene; - return pv.Mark.prototype.anchor.call(this, name) - .left(function() { - var s = this.scene.target[this.index]; - switch (this.name()) { - case "bottom": - case "top": - case "center": return s.left; - case "left": return null; - } - return s.left + s.shapeRadius; - }) - .right(function() { - var s = this.scene.target[this.index]; - return this.name() == "left" ? s.right + s.shapeRadius : null; - }) - .top(function() { - var s = this.scene.target[this.index]; - switch (this.name()) { - case "left": - case "right": - case "center": return s.top; - case "top": return null; - } - return s.top + s.shapeRadius; - }) - .bottom(function() { - var s = this.scene.target[this.index]; - return this.name() == "top" ? s.bottom + s.shapeRadius : null; - }) - .textAlign(function() { - switch (this.name()) { - case "left": return "right"; - case "bottom": - case "top": - case "center": return "center"; - } - return "left"; - }) - .textBaseline(function() { - switch (this.name()) { - case "right": - case "left": - case "center": return "middle"; - case "bottom": return "top"; - } - return "bottom"; - }); -}; - -/** @private Sets radius based on size or vice versa. */ -pv.Dot.prototype.buildImplied = function(s) { - var r = s.shapeRadius, z = s.shapeSize; - if (r == null) { - if (z == null) { - s.shapeSize = 20.25; - s.shapeRadius = 4.5; - } else { - s.shapeRadius = Math.sqrt(z); - } - } else if (z == null) { - s.shapeSize = r * r; - } - pv.Mark.prototype.buildImplied.call(this, s); -}; - -pv.Dot.prototype.getShapeCore = function(scenes, index){ - var s = scenes[index]; - - var radius = s.shapeRadius, - cx = s.left, - cy = s.top; - - // TODO: square and diamond break when angle is used - - switch(s.shape){ - case 'diamond': - radius *= Math.SQRT2; - // the following comment is for jshint - /* falls through */ - case 'square': - case 'cross': - return new pv.Shape.Rect(cx - radius, cy - radius, 2*radius, 2*radius); - } - - // 'circle' included - - return new pv.Shape.Circle(cx, cy, radius); -}; -/** - * Constructs a new label mark with default properties. Labels are not typically - * constructed directly, but by adding to a panel or an existing mark via - * {@link pv.Mark#add}. - * - * @class Represents a text label, allowing textual annotation of other marks or - * arbitrary text within the visualization. The character data must be plain - * text (unicode), though the text can be styled using the {@link #font} - * property. If rich text is needed, external HTML elements can be overlaid on - * the canvas by hand. - * - *

Labels are positioned using the box model, similarly to {@link Dot}. Thus, - * a label has no width or height, but merely a text anchor location. The text - * is positioned relative to this anchor location based on the - * {@link #textAlign}, {@link #textBaseline} and {@link #textMargin} properties. - * Furthermore, the text may be rotated using {@link #textAngle}. - * - *

Labels ignore events, so as to not interfere with event handlers on - * underlying marks, such as bars. In the future, we may support event handlers - * on labels. - * - *

See also the Label guide. - * - * @extends pv.Mark - */ -pv.Label = function() { - pv.Mark.call(this); -}; - -pv.Label.prototype = pv.extend(pv.Mark) - .property("text", String) - .property("font", String) - .property("textAngle", Number) - .property("textStyle", pv.color) - .property("textAlign", String) - .property("textBaseline", String) - .property("textMargin", Number) - .property("textDecoration", String) - .property("textShadow", String); - -pv.Label.prototype.type = "label"; - -/** - * The character data to render; a string. The default value of the text - * property is the identity function, meaning the label's associated datum will - * be rendered using its toString. - * - * @type string - * @name pv.Label.prototype.text - */ - -/** - * The font format, per the CSS Level 2 specification. The default font is "10px - * sans-serif", for consistency with the HTML 5 canvas element specification. - * Note that since text is not wrapped, any line-height property will be - * ignored. The other font-style, font-variant, font-weight, font-size and - * font-family properties are supported. - * - * @see CSS2 fonts - * @type string - * @name pv.Label.prototype.font - */ - -/** - * The rotation angle, in radians. Text is rotated clockwise relative to the - * anchor location. For example, with the default left alignment, an angle of - * Math.PI / 2 causes text to proceed downwards. The default angle is zero. - * - * @type number - * @name pv.Label.prototype.textAngle - */ - -/** - * The text color. The name "textStyle" is used for consistency with "fillStyle" - * and "strokeStyle", although it might be better to rename this property (and - * perhaps use the same name as "strokeStyle"). The default color is black. - * - * @type string - * @name pv.Label.prototype.textStyle - * @see pv.color - */ - -/** - * The horizontal text alignment. One of:

    - * - *
  • left - *
  • center - *
  • right - * - *
The default horizontal alignment is left. - * - * @type string - * @name pv.Label.prototype.textAlign - */ - -/** - * The vertical text alignment. One of:
    - * - *
  • top - *
  • middle - *
  • bottom - * - *
The default vertical alignment is bottom. - * - * @type string - * @name pv.Label.prototype.textBaseline - */ - -/** - * The text margin; may be specified in pixels, or in font-dependent units (such - * as ".1ex"). The margin can be used to pad text away from its anchor location, - * in a direction dependent on the horizontal and vertical alignment - * properties. For example, if the text is left- and middle-aligned, the margin - * shifts the text to the right. The default margin is 3 pixels. - * - * @type number - * @name pv.Label.prototype.textMargin - */ - -/** - * A list of shadow effects to be applied to text, per the CSS Text Level 3 - * text-shadow property. An example specification is "0.1em 0.1em 0.1em - * rgba(0,0,0,.5)"; the first length is the horizontal offset, the second the - * vertical offset, and the third the blur radius. - * - * @see CSS3 text - * @type string - * @name pv.Label.prototype.textShadow - */ - -/** - * A list of decoration to be applied to text, per the CSS Text Level 3 - * text-decoration property. An example specification is "underline". - * - * @see CSS3 text - * @type string - * @name pv.Label.prototype.textDecoration - */ - -/** - * Default properties for labels. See the individual properties for the default - * values. - * - * @type pv.Label - */ -pv.Label.prototype.defaults = new pv.Label() - .extend(pv.Mark.prototype.defaults) - .events("none") - .text(pv.identity) - .font("10px sans-serif") - .textAngle(0) - .textStyle("black") - .textAlign("left") - .textBaseline("bottom") - .textMargin(3); - - -pv.Label.prototype.getShapeCore = function(scenes, index){ - var s = scenes[index]; - - var size = pv.Text.measure(s.text, s.font); - - return pv.Label.getPolygon( - size.width, - size.height, - s.textAlign, - s.textBaseline, - s.textAngle, - s.textMargin) - .apply(pv.Transform.identity.translate(s.left, s.top)); -}; - -pv.Label.getPolygon = function(textWidth, textHeight, align, baseline, angle, margin){ - // x, y are the position of the left-bottom corner - // of the text relative to its anchor point (at x=0,y=0) - // x points right, y points down - var x, y; - - switch (baseline) { - case "middle": - y = textHeight / 2; // estimate middle (textHeight is not em, the height of capital M) - break; - - case "top": - y = margin + textHeight; - break; - - case "bottom": - y = -margin; - break; - } - - switch (align) { - case "right": - x = -margin -textWidth; - break; - - case "center": - x = -textWidth / 2; - break; - - case "left": - x = margin; - break; - } - - var bl = new pv.Vector(x, y); - var br = bl.plus(textWidth, 0); - var tr = br.plus(0, -textHeight); - var tl = bl.plus(0, -textHeight); - - // Rotate - - if(angle !== 0){ - bl = bl.rotate(angle); - br = br.rotate(angle); - tl = tl.rotate(angle); - tr = tr.rotate(angle); - } - - return new pv.Shape.Polygon([bl, br, tr, tl]); -}; -/** - * Constructs a new line mark with default properties. Lines are not typically - * constructed directly, but by adding to a panel or an existing mark via - * {@link pv.Mark#add}. - * - * @class Represents a series of connected line segments, or polyline, - * that can be stroked with a configurable color and thickness. Each - * articulation point in the line corresponds to a datum; for n points, - * n-1 connected line segments are drawn. The point is positioned using - * the box model. Arbitrary paths are also possible, allowing radar plots and - * other custom visualizations. - * - *

Like areas, lines can be stroked and filled with arbitrary colors. In most - * cases, lines are only stroked, but the fill style can be used to construct - * arbitrary polygons. - * - *

See also the Line guide. - * - * @extends pv.Mark - */ -pv.Line = function() { - pv.Mark.call(this); -}; - -pv.Line.prototype = pv.extend(pv.Mark) - .property("lineWidth", Number) - .property("lineJoin", String) - .property("strokeMiterLimit", Number) - .property("lineCap", String) - .property("strokeStyle", pv.fillStyle) - .property("strokeDasharray", String) - .property("fillStyle", pv.fillStyle) - .property("segmented", pv.Area.castSegmented) - .property("interpolate", String) - .property("eccentricity", Number) - .property("tension", Number); - -pv.Line.prototype.type = "line"; - -/** - * The width of stroked lines, in pixels; used in conjunction with - * strokeStyle to stroke the line. - * - * @type number - * @name pv.Line.prototype.lineWidth - */ - -/** - * The style of stroked lines; used in conjunction with lineWidth to - * stroke the line. The default value of this property is a categorical color. - * - * @type string - * @name pv.Line.prototype.strokeStyle - * @see pv.color - */ - -/** - * The type of corners where two lines meet. Accepted values are "bevel", - * "round" and "miter". The default value is "miter". - * - *

For segmented lines, only "miter" joins and "linear" interpolation are - * currently supported. Any other value, including null, will disable joins, - * producing disjoint line segments. Note that the miter joins must be computed - * manually (at least in the current SVG renderer); since this calculation may - * be expensive and unnecessary for small lines, specifying null can improve - * performance significantly. - * - *

This property is fixed. See {@link pv.Mark}. - * - * @type string - * @name pv.Line.prototype.lineJoin - */ - -/** - * The line fill style; if non-null, the interior of the line is closed and - * filled with the specified color. The default value of this property is a - * null, meaning that lines are not filled by default. - * - *

This property is fixed. See {@link pv.Mark}. - * - * @type string - * @name pv.Line.prototype.fillStyle - * @see pv.color - */ - -/** - * Whether the line is segmented; whether variations in stroke style, line width - * and the other properties are treated as fixed. Rendering segmented lines is - * noticeably slower than non-segmented lines. - * - *

This property is fixed. See {@link pv.Mark}. - * - * @type boolean - * @name pv.Line.prototype.segmented - */ - -/** - * How to interpolate between values. Linear interpolation ("linear") is the - * default, producing a straight line between points. For piecewise constant - * functions (i.e., step functions), either "step-before" or "step-after" can be - * specified. To draw a clockwise circular arc between points, specify "polar"; - * to draw a counterclockwise circular arc between points, specify - * "polar-reverse". To draw open uniform b-splines, specify "basis". To draw - * cardinal splines, specify "cardinal"; see also {@link #tension}. - * - *

This property is fixed. See {@link pv.Mark}. - * - * @type string - * @name pv.Line.prototype.interpolate - */ - -/** - * The eccentricity of polar line segments; used in conjunction with - * interpolate("polar"). The default value of 0 means that line segments are - * drawn as circular arcs. A value of 1 draws a straight line. A value between 0 - * and 1 draws an elliptical arc with the given eccentricity. - * - * @type number - * @name pv.Line.prototype.eccentricity - */ - -/** - * The tension of cardinal splines; used in conjunction with - * interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with - * the given tension. In some sense, the tension can be interpreted as the - * "length" of the tangent; a tension of 1 will yield all zero tangents (i.e., - * linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The - * default value is 0.7. - * - *

This property is fixed. See {@link pv.Mark}. - * - * @type number - * @name pv.Line.prototype.tension - */ - -/** - * Default properties for lines. By default, there is no fill and the stroke - * style is a categorical color. The default interpolation is linear. - * - * @type pv.Line - */ -pv.Line.prototype.defaults = new pv.Line() - .extend(pv.Mark.prototype.defaults) - .lineWidth(1.5) - .strokeStyle(pv.Colors.category10().by(pv.parent)) - .interpolate("linear") - .eccentricity(0) - .tension(.7) - .lineJoin("miter") - .strokeMiterLimit(8) - .lineCap("butt") - .strokeDasharray("none"); - -/** @private Reuse Area's implementation for segmented bind & build. */ -pv.Line.prototype.bind = pv.Area.prototype.bind; -pv.Line.prototype.buildInstance = pv.Area.prototype.buildInstance; - -/** - * Constructs a new line anchor with default properties. Lines support five - * different anchors:

    - * - *
  • top - *
  • left - *
  • center - *
  • bottom - *
  • right - * - *
In addition to positioning properties (left, right, top bottom), the - * anchors support text rendering properties (text-align, text-baseline). Text is - * rendered to appear outside the line. Note that this behavior is different - * from other mark anchors, which default to rendering text inside the - * mark. - * - *

For consistency with the other mark types, the anchor positions are - * defined in terms of their opposite edge. For example, the top anchor defines - * the bottom property, such that a bar added to the top anchor grows upward. - * - * @param {string} name the anchor name; either a string or a property function. - * @returns {pv.Anchor} - */ -pv.Line.prototype.anchor = function(name) { - return pv.Area.prototype.anchor.call(this, name) - .textAlign(function(d) { - switch (this.name()) { - case "left": return "right"; - case "bottom": - case "top": - case "center": return "center"; - case "right": return "left"; - } - }) - .textBaseline(function(d) { - switch (this.name()) { - case "right": - case "left": - case "center": return "middle"; - case "top": return "bottom"; - case "bottom": return "top"; - } - }); -}; - -pv.Line.prototype.getShapeCore = function(scenes, index){ - var s = scenes[index]; - var s2 = index + 1 < scenes.length ? scenes[index + 1] : null; - if(s2 == null || !s2.visible){ - return new pv.Shape.Point(s.left, s.top); - } - - return new pv.Shape.Line(s.left, s.top, s2.left, s2.top); -}; -/** - * Constructs a new rule with default properties. Rules are not typically - * constructed directly, but by adding to a panel or an existing mark via - * {@link pv.Mark#add}. - * - * @class Represents a horizontal or vertical rule. Rules are frequently used - * for axes and grid lines. For example, specifying only the bottom property - * draws horizontal rules, while specifying only the left draws vertical - * rules. Rules can also be used as thin bars. The visual style is controlled in - * the same manner as lines. - * - *

Rules are positioned exclusively the standard box model properties. The - * following combinations of properties are supported: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
PropertiesOrientation
leftvertical
rightvertical
left, bottom, topvertical
right, bottom, topvertical
tophorizontal
bottomhorizontal
top, left, righthorizontal
bottom, left, righthorizontal
left, top, heightvertical
left, bottom, heightvertical
right, top, heightvertical
right, bottom, heightvertical
left, top, widthhorizontal
left, bottom, widthhorizontal
right, top, widthhorizontal
right, bottom, widthhorizontal
- * - *

Small rules can be used as tick marks; alternatively, a {@link Dot} with - * the "tick" shape can be used. - * - *

See also the Rule guide. - * - * @see pv.Line - * @extends pv.Mark - */ -pv.Rule = function() { - pv.Mark.call(this); -}; - -pv.Rule.prototype = pv.extend(pv.Mark) - .property("width", Number) - .property("height", Number) - .property("lineWidth", Number) - .property("strokeStyle", pv.fillStyle) - .property("lineCap", String) - .property("strokeDasharray", String); - -pv.Rule.prototype.type = "rule"; - -/** - * The width of the rule, in pixels. If the left position is specified, the rule - * extends rightward from the left edge; if the right position is specified, the - * rule extends leftward from the right edge. - * - * @type number - * @name pv.Rule.prototype.width - */ - -/** - * The height of the rule, in pixels. If the bottom position is specified, the - * rule extends upward from the bottom edge; if the top position is specified, - * the rule extends downward from the top edge. - * - * @type number - * @name pv.Rule.prototype.height - */ - -/** - * The width of stroked lines, in pixels; used in conjunction with - * strokeStyle to stroke the rule. The default value is 1 pixel. - * - * @type number - * @name pv.Rule.prototype.lineWidth - */ - -/** - * The style of stroked lines; used in conjunction with lineWidth to - * stroke the rule. The default value of this property is black. - * - * @type string - * @name pv.Rule.prototype.strokeStyle - * @see pv.color - */ - -/** - * Default properties for rules. By default, a single-pixel black line is - * stroked. - * - * @type pv.Rule - */ -pv.Rule.prototype.defaults = new pv.Rule() - .extend(pv.Mark.prototype.defaults) - .lineWidth(1) - .strokeStyle("black") - .antialias(false) - .lineCap("butt") - .strokeDasharray("none"); - -/** - * Constructs a new rule anchor with default properties. Rules support five - * different anchors:

    - * - *
  • top - *
  • left - *
  • center - *
  • bottom - *
  • right - * - *
In addition to positioning properties (left, right, top bottom), the - * anchors support text rendering properties (text-align, text-baseline). Text is - * rendered to appear outside the rule. Note that this behavior is different - * from other mark anchors, which default to rendering text inside the - * mark. - * - *

For consistency with the other mark types, the anchor positions are - * defined in terms of their opposite edge. For example, the top anchor defines - * the bottom property, such that a bar added to the top anchor grows upward. - * - * @param {string} name the anchor name; either a string or a property function. - * @returns {pv.Anchor} - */ -pv.Rule.prototype.anchor = pv.Line.prototype.anchor; - -/** @private Sets width or height based on orientation. */ -pv.Rule.prototype.buildImplied = function(s) { - var l = s.left, r = s.right, t = s.top, b = s.bottom; - - /* Determine horizontal or vertical orientation. */ - if ((s.width != null) - || ((l == null) && (r == null)) - || ((r != null) && (l != null))) { - s.height = 0; - } else { - s.width = 0; - } - - pv.Mark.prototype.buildImplied.call(this, s); -}; - -pv.Rule.prototype.getShapeCore = function(scenes, index){ - var s = scenes[index]; - return new pv.Shape.Line( - s.left, s.top, - s.left + s.width, s.top + s.height); -}; - -/** - * Constructs a new, empty panel with default properties. Panels, with the - * exception of the root panel, are not typically constructed directly; instead, - * they are added to an existing panel or mark via {@link pv.Mark#add}. - * - * @class Represents a container mark. Panels allow repeated or nested - * structures, commonly used in small multiple displays where a small - * visualization is tiled to facilitate comparison across one or more - * dimensions. Other types of visualizations may benefit from repeated and - * possibly overlapping structure as well, such as stacked area charts. Panels - * can also offset the position of marks to provide padding from surrounding - * content. - * - *

All Protovis displays have at least one panel; this is the root panel to - * which marks are rendered. The box model properties (four margins, width and - * height) are used to offset the positions of contained marks. The data - * property determines the panel count: a panel is generated once per associated - * datum. When nested panels are used, property functions can declare additional - * arguments to access the data associated with enclosing panels. - * - *

Panels can be rendered inline, facilitating the creation of sparklines. - * This allows designers to reuse browser layout features, such as text flow and - * tables; designers can also overlay HTML elements such as rich text and - * images. - * - *

All panels have a children array (possibly empty) containing the - * child marks in the order they were added. Panels also have a root - * field which points to the root (outermost) panel; the root panel's root field - * points to itself. - * - *

See also the Protovis guide. - * - * @extends pv.Bar - */ -pv.Panel = function() { - pv.Bar.call(this); - - /** - * The child marks; zero or more {@link pv.Mark}s in the order they were - * added. - * - * @see #add - * @type pv.Mark[] - */ - this.children = []; - this.root = this; - - /** - * The internal $dom field is set by the Protovis loader; see lang/init.js. It - * refers to the script element that contains the Protovis specification, so - * that the panel knows where in the DOM to insert the generated SVG element. - * - * @private - */ - this.$dom = pv.$ && pv.$.s; -}; - -pv.Panel.prototype = pv.extend(pv.Bar) - .property("transform") - .property("overflow", String) - .property("canvas", function(c) { - return (typeof c == "string") - ? document.getElementById(c) - : c; // assume that c is the passed-in element - }); - -pv.Panel.prototype.type = "panel"; - -/** - * The canvas element; either the string ID of the canvas element in the current - * document, or a reference to the canvas element itself. If null, a canvas - * element will be created and inserted into the document at the location of the - * script element containing the current Protovis specification. This property - * only applies to root panels and is ignored on nested panels. - * - *

Note: the "canvas" element here refers to a div (or other suitable - * HTML container element), not a canvas element. The name of - * this property is a historical anachronism from the first implementation that - * used HTML 5 canvas, rather than SVG. - * - * @type string - * @name pv.Panel.prototype.canvas - */ - -/** - * Specifies whether child marks are clipped when they overflow this panel. - * This affects the clipping of all this panel's descendant marks. - * - * @type string - * @name pv.Panel.prototype.overflow - * @see CSS2 - */ - -/** - * The transform to be applied to child marks. The default transform is - * identity, which has no effect. Note that the panel's own fill and stroke are - * not affected by the transform, and panel's transform only affects the - * scale of child marks, not the panel itself. - * - * @type pv.Transform - * @name pv.Panel.prototype.transform - * @see pv.Mark#scale - */ - -/** - * The number of descendant marks that are animating. - * Only the root panel has this property set. - * - * @type number - */ -pv.Panel.prototype.animatingCount = 0; - - -/** - * The number of children that have a non-zero {@link pv.Mark#_zOrder}. - * - * @type number - */ -pv.Panel.prototype.zOrderChildCount = 0; - -/** - * Default properties for panels. By default, the margins are zero, the fill - * style is transparent. - * - * @type pv.Panel - */ -pv.Panel.prototype.defaults = new pv.Panel() - .extend(pv.Bar.prototype.defaults) - .fillStyle(null) // override Bar default - .overflow("visible"); - -/** - * Returns an anchor with the specified name. This method is overridden such - * that adding to a panel's anchor adds to the panel, rather than to the panel's - * parent. - * - * @param {string} name the anchor name; either a string or a property function. - * @returns {pv.Anchor} the new anchor. - */ -pv.Panel.prototype.anchor = function(name) { - var anchor = pv.Bar.prototype.anchor.call(this, name); - anchor.parent = this; - return anchor; -}; - -/** - * Adds a new mark of the specified type to this panel. Unlike the normal - * {@link Mark#add} behavior, adding a mark to a panel does not cause the mark - * to inherit from the panel. Since the contained marks are offset by the panel - * margins already, inheriting properties is generally undesirable; of course, - * it is always possible to change this behavior by calling {@link Mark#extend} - * explicitly. - * - * @param {function} type the type of the new mark to add. - * @returns {pv.Mark} the new mark. - */ -pv.Panel.prototype.add = function(type) { - var child = new type(); - child.parent = this; - child.root = this.root; - child.childIndex = this.children.length; - this.children.push(child); - return child; -}; - -/** @private Bind this panel, then any child marks recursively. */ -pv.Panel.prototype.bind = function() { - pv.Mark.prototype.bind.call(this); - - var children = this.children; - for (var i = 0, n = children.length ; i < n ; i++) { - children[i].bind(); - } -}; - -/** - * @private Evaluates all of the properties for this panel for the specified - * instance s in the scene graph, including recursively building the - * scene graph for child marks. - * - * @param s a node in the scene graph; the instance of the panel to build. - * @see Mark#scene - */ -pv.Panel.prototype.buildInstance = function(s) { - pv.Bar.prototype.buildInstance.call(this, s); - - if (!s.visible) return; - - /* - * Multiply the current scale factor by this panel's transform. Also clear the - * default index as we recurse into child marks; it will be reset to the - * current index when the next panel instance is built. - */ - var scale = this.scale * s.transform.k; - pv.Mark.prototype.index = -1; - - /* - * Build each child, passing in the parent (this panel) scene graph node. The - * child mark's scene is initialized from the corresponding entry in the - * existing scene graph, such that properties from the previous build can be - * reused; this is largely to facilitate the recycling of SVG elements. - */ - var child; - var children = this.children; - var childScenes = s.children || (s.children = []); - for (var i = 0, n = children.length; i < n; i++) { - child = children[i]; - child.scene = childScenes[i]; // possibly undefined - child.scale = scale; - child.build(); - } - - /* - * Once the child marks have been built, the new scene graph nodes are removed - * from the child marks and placed into the scene graph. The nodes cannot - * remain on the child nodes because this panel (or a parent panel) may be - * instantiated multiple times! - */ - for (var i = 0; i < n; i++) { - child = children[i]; - childScenes[i] = child.scene; - delete child.scene; - delete child.scale; - } - - /* Delete any expired child scenes. */ - childScenes.length = n; -}; - -/** - * @private Computes the implied properties for this panel for the specified - * instance s in the scene graph. Panels have two implied - * properties:

    - * - *
  • The canvas property references the DOM element, typically a DIV, - * that contains the SVG element that is used to display the visualization. This - * property may be specified as a string, referring to the unique ID of the - * element in the DOM. The string is converted to a reference to the DOM - * element. The width and height of the SVG element is inferred from this DOM - * element. If no canvas property is specified, a new SVG element is created and - * inserted into the document, using the panel dimensions; see - * {@link #createCanvas}. - * - *
  • The children array, while not a property per se, contains the - * scene graph for each child mark. This array is initialized to be empty, and - * is populated above in {@link #buildInstance}. - * - *
The current implementation creates the SVG element, if necessary, during - * the build phase; in the future, it may be preferrable to move this to the - * update phase, although then the canvas property would be undefined. In - * addition, DOM inspection is necessary to define the implied width and height - * properties that may be inferred from the DOM. - * - * @param s a node in the scene graph; the instance of the panel to build. - */ -pv.Panel.prototype.buildImplied = function(s) { - if (!this.parent) { - var c = s.canvas; - if (pv.renderer() === "batik") { - if (c) { - if (c.$panel != this) { - pv.Panel.updateCreateId(c); - c.$panel = this; - while (c.lastChild) c.removeChild(c.lastChild); - } - } else { - c = document.lastChild; - } - } else if (c) { - /* Clear the container if it's not associated with this panel. */ - if (c.$panel != this) { - pv.Panel.updateCreateId(c); - c.$panel = this; - while (c.lastChild) c.removeChild(c.lastChild); - } - - /* If width and height weren't specified, inspect the container. */ - var w, h; - if (s.width == null) { - w = parseFloat(pv.css(c, "width")); - s.width = w - s.left - s.right; - } - if (s.height == null) { - h = parseFloat(pv.css(c, "height")); - s.height = h - s.top - s.bottom; - } - } else { - var cache = this.$canvas || (this.$canvas = []); - if (!(c = cache[this.index])) { - c = cache[this.index] = document.createElement(pv.renderer() == "svgweb" ? "div" : "span"); // SVGWeb requires a div, not a span - if (this.$dom) { // script element for text/javascript+protovis - this.$dom.parentNode.insertBefore(c, this.$dom); - } else { // find the last element in the body - var n = document.body; - while (n.lastChild && n.lastChild.tagName) n = n.lastChild; - if (n != document.body) n = n.parentNode; - n.appendChild(c); - } - } - } - s.canvas = c; - } - if (!s.transform) s.transform = pv.Transform.identity; - pv.Mark.prototype.buildImplied.call(this, s); -}; - -pv.Panel.updateCreateId = function(c){ - c.$pvCreateId = (c.$pvCreateId || 0) + 1; -}; -/** - * Constructs a new image with default properties. Images are not typically - * constructed directly, but by adding to a panel or an existing mark via - * {@link pv.Mark#add}. - * - * @class Represents an image, either a static resource or a dynamically- - * generated pixel buffer. Images share the same layout and style properties as - * bars. The external image resource is specified via the {@link #url} - * property. The optional fill, if specified, appears beneath the image, while - * the optional stroke appears above the image. - * - *

Dynamic images such as heatmaps are supported using the {@link #image} - * psuedo-property. This function is passed the x and y index, in - * addition to the current data stack. The return value is a {@link pv.Color}, - * or null for transparent. A string can also be returned, which will be parsed - * into a color; however, it is typically much faster to return an object with - * r, g, b and a attributes, to avoid the - * cost of parsing and object instantiation. - * - *

See {@link pv.Bar} for details on positioning properties. - * - * @extends pv.Bar - */ -pv.Image = function() { - pv.Bar.call(this); -}; - -pv.Image.prototype = pv.extend(pv.Bar) - .property("url", String) - .property("imageWidth", Number) - .property("imageHeight", Number); - -pv.Image.prototype.type = "image"; - -/** - * The URL of the image to display. The set of supported image types is - * browser-dependent; PNG and JPEG are recommended. - * - * @type string - * @name pv.Image.prototype.url - */ - -/** - * The width of the image in pixels. For static images, this property is - * computed implicitly from the loaded image resources. For dynamic images, this - * property can be used to specify the width of the pixel buffer; otherwise, the - * value is derived from the width property. - * - * @type number - * @name pv.Image.prototype.imageWidth - */ - -/** - * The height of the image in pixels. For static images, this property is - * computed implicitly from the loaded image resources. For dynamic images, this - * property can be used to specify the height of the pixel buffer; otherwise, the - * value is derived from the height property. - * - * @type number - * @name pv.Image.prototype.imageHeight - */ - -/** - * Default properties for images. By default, there is no stroke or fill style. - * - * @type pv.Image - */ -pv.Image.prototype.defaults = new pv.Image() - .extend(pv.Bar.prototype.defaults) - .fillStyle(null); - -/** - * Specifies the dynamic image function. By default, no image function is - * specified and the url property is used to load a static image - * resource. If an image function is specified, it will be invoked for each - * pixel in the image, based on the related imageWidth and - * imageHeight properties. - * - *

For example, given a two-dimensional array heatmap, containing - * numbers in the range [0, 1] in row-major order, a simple monochrome heatmap - * image can be specified as: - * - *

vis.add(pv.Image)
- *     .imageWidth(heatmap[0].length)
- *     .imageHeight(heatmap.length)
- *     .image(pv.ramp("white", "black").by(function(x, y) heatmap[y][x]));
- * - * For fastest performance, use an ordinal scale which caches the fixed color - * palette, or return an object literal with r, g, b - * and a attributes. A {@link pv.Color} or string can also be returned, - * though this typically results in slower performance. - * - * @param {function} f the new sizing function. - * @returns {pv.Layout.Pack} this. - */ -pv.Image.prototype.image = function(f) { - /** @private */ - this.$image = function() { - var c = f.apply(this, arguments); - return c == null ? pv.Color.transparent - : typeof c == "string" ? pv.color(c) - : c; - }; - return this; -}; - -/** @private Scan the proto chain for an image function. */ -pv.Image.prototype.bind = function() { - pv.Bar.prototype.bind.call(this); - var binds = this.binds, mark = this; - do { - binds.image = mark.$image; - } while (!binds.image && (mark = mark.proto)); -}; - -/** @private */ -pv.Image.prototype.buildImplied = function(s) { - pv.Bar.prototype.buildImplied.call(this, s); - if (!s.visible) return; - - /* Compute the implied image dimensions. */ - if (s.imageWidth == null) s.imageWidth = s.width; - if (s.imageHeight == null) s.imageHeight = s.height; - - /* Compute the pixel values. */ - if ((s.url == null) && this.binds.image) { - - /* Cache the canvas element to reuse across renders. */ - var canvas = this.$canvas || (this.$canvas = document.createElement("canvas")), - context = canvas.getContext("2d"), - w = s.imageWidth, - h = s.imageHeight, - stack = pv.Mark.stack, - data; - - /* Evaluate the image function, storing into a CanvasPixelArray. */ - canvas.width = w; - canvas.height = h; - data = (s.image = context.createImageData(w, h)).data; - stack.unshift(null, null); - for (var y = 0, p = 0; y < h; y++) { - stack[1] = y; - for (var x = 0; x < w; x++) { - stack[0] = x; - var color = this.binds.image.apply(this, stack); - data[p++] = color.r; - data[p++] = color.g; - data[p++] = color.b; - data[p++] = 255 * color.a; - } - } - stack.splice(0, 2); - } -}; -/** - * Constructs a new wedge with default properties. Wedges are not typically - * constructed directly, but by adding to a panel or an existing mark via - * {@link pv.Mark#add}. - * - * @class Represents a wedge, or pie slice. Specified in terms of start and end - * angle, inner and outer radius, wedges can be used to construct donut charts - * and polar bar charts as well. If the {@link #angle} property is used, the end - * angle is implied by adding this value to start angle. By default, the start - * angle is the previously-generated wedge's end angle. This design allows - * explicit control over the wedge placement if desired, while offering - * convenient defaults for the construction of radial graphs. - * - *

The center point of the circle is positioned using the standard box model. - * The wedge can be stroked and filled, similar to {@link pv.Bar}. - * - *

See also the Wedge guide. - * - * @extends pv.Mark - */ -pv.Wedge = function() { - pv.Mark.call(this); -}; - -pv.Wedge.prototype = pv.extend(pv.Mark) - .property("startAngle", Number) - .property("endAngle", Number) - .property("angle", Number) - .property("innerRadius", Number) - .property("outerRadius", Number) - .property("lineWidth", Number) - .property("strokeStyle", pv.fillStyle) - .property("lineJoin", String) - .property("strokeMiterLimit", Number) - .property("lineCap", String) - .property("strokeDasharray", String) - .property("fillStyle", pv.fillStyle); - -pv.Wedge.prototype.type = "wedge"; - -/** - * The start angle of the wedge, in radians. The start angle is measured - * clockwise from the 3 o'clock position. The default value of this property is - * the end angle of the previous instance (the {@link Mark#sibling}), or -PI / 2 - * for the first wedge; for pie and donut charts, typically only the - * {@link #angle} property needs to be specified. - * - * @type number - * @name pv.Wedge.prototype.startAngle - */ - -/** - * The end angle of the wedge, in radians. If not specified, the end angle is - * implied as the start angle plus the {@link #angle}. - * - * @type number - * @name pv.Wedge.prototype.endAngle - */ - -/** - * The angular span of the wedge, in radians. This property is used if end angle - * is not specified. - * - * @type number - * @name pv.Wedge.prototype.angle - */ - -/** - * The inner radius of the wedge, in pixels. The default value of this property - * is zero; a positive value will produce a donut slice rather than a pie slice. - * The inner radius can vary per-wedge. - * - * @type number - * @name pv.Wedge.prototype.innerRadius - */ - -/** - * The outer radius of the wedge, in pixels. This property is required. For - * pies, only this radius is required; for donuts, the inner radius must be - * specified as well. The outer radius can vary per-wedge. - * - * @type number - * @name pv.Wedge.prototype.outerRadius - */ - -/** - * The width of stroked lines, in pixels; used in conjunction with - * strokeStyle to stroke the wedge's border. - * - * @type number - * @name pv.Wedge.prototype.lineWidth - */ - -/** - * The style of stroked lines; used in conjunction with lineWidth to - * stroke the wedge's border. The default value of this property is null, - * meaning wedges are not stroked by default. - * - * @type string - * @name pv.Wedge.prototype.strokeStyle - * @see pv.color - */ - -/** - * The wedge fill style; if non-null, the interior of the wedge is filled with - * the specified color. The default value of this property is a categorical - * color. - * - * @type string - * @name pv.Wedge.prototype.fillStyle - * @see pv.color - */ - -/** - * Default properties for wedges. By default, there is no stroke and the fill - * style is a categorical color. - * - * @type pv.Wedge - */ -pv.Wedge.prototype.defaults = new pv.Wedge() - .extend(pv.Mark.prototype.defaults) - .startAngle(function() { - var s = this.sibling(); - return s ? s.endAngle : -Math.PI / 2; - }) - .innerRadius(0) - .lineWidth(1.5) - .strokeStyle(null) - .fillStyle(pv.Colors.category20().by(pv.index)) - .lineJoin("miter") - .strokeMiterLimit(8) - .lineCap("butt") - .strokeDasharray("none"); - -/** - * Returns the mid-radius of the wedge, which is defined as half-way between the - * inner and outer radii. - * - * @see #innerRadius - * @see #outerRadius - * @returns {number} the mid-radius, in pixels. - */ -pv.Wedge.prototype.midRadius = function() { - return (this.innerRadius() + this.outerRadius()) / 2; -}; - -/** - * Returns the mid-angle of the wedge, which is defined as half-way between the - * start and end angles. - * - * @see #startAngle - * @see #endAngle - * @returns {number} the mid-angle, in radians. - */ -pv.Wedge.prototype.midAngle = function() { - return (this.startAngle() + this.endAngle()) / 2; -}; - -/** - * Constructs a new wedge anchor with default properties. Wedges support five - * different anchors:

    - * - *
  • outer - *
  • inner - *
  • center - *
  • start - *
  • end - * - *
In addition to positioning properties (left, right, top bottom), the - * anchors support text rendering properties (text-align, text-baseline, - * textAngle). Text is rendered to appear inside the wedge. - * - * @param {string} name the anchor name; either a string or a property function. - * @returns {pv.Anchor} - */ -pv.Wedge.prototype.anchor = function(name) { - function partial(s) { return s.innerRadius || s.angle < 2 * Math.PI; } - function midRadius(s) { return (s.innerRadius + s.outerRadius) / 2; } - function midAngle(s) { return (s.startAngle + s.endAngle) / 2; } - return pv.Mark.prototype.anchor.call(this, name) - .left(function() { - var s = this.scene.target[this.index]; - if (partial(s)) switch (this.name()) { - case "outer": return s.left + s.outerRadius * Math.cos(midAngle(s)); - case "inner": return s.left + s.innerRadius * Math.cos(midAngle(s)); - case "start": return s.left + midRadius(s) * Math.cos(s.startAngle); - case "center": return s.left + midRadius(s) * Math.cos(midAngle(s)); - case "end": return s.left + midRadius(s) * Math.cos(s.endAngle); - } - return s.left; - }) - .top(function() { - var s = this.scene.target[this.index]; - if (partial(s)) switch (this.name()) { - case "outer": return s.top + s.outerRadius * Math.sin(midAngle(s)); - case "inner": return s.top + s.innerRadius * Math.sin(midAngle(s)); - case "start": return s.top + midRadius(s) * Math.sin(s.startAngle); - case "center": return s.top + midRadius(s) * Math.sin(midAngle(s)); - case "end": return s.top + midRadius(s) * Math.sin(s.endAngle); - } - return s.top; - }) - .textAlign(function() { - var s = this.scene.target[this.index]; - if (partial(s)) switch (this.name()) { - case "outer": return pv.Wedge.upright(midAngle(s)) ? "right" : "left"; - case "inner": return pv.Wedge.upright(midAngle(s)) ? "left" : "right"; - } - return "center"; - }) - .textBaseline(function() { - var s = this.scene.target[this.index]; - if (partial(s)) switch (this.name()) { - case "start": return pv.Wedge.upright(s.startAngle) ? "top" : "bottom"; - case "end": return pv.Wedge.upright(s.endAngle) ? "bottom" : "top"; - } - return "middle"; - }) - .textAngle(function() { - var s = this.scene.target[this.index], a = 0; - if (partial(s)) switch (this.name()) { - case "center": - case "inner": - case "outer": a = midAngle(s); break; - case "start": a = s.startAngle; break; - case "end": a = s.endAngle; break; - } - return pv.Wedge.upright(a) ? a : (a + Math.PI); - }); -}; - -/** - * Returns true if the specified angle is considered "upright", as in, text - * rendered at that angle would appear upright. If the angle is not upright, - * text is rotated 180 degrees to be upright, and the text alignment properties - * are correspondingly changed. - * - * @param {number} angle an angle, in radius. - * @returns {boolean} true if the specified angle is upright. - */ -pv.Wedge.upright = function(angle) { - angle = angle % (2 * Math.PI); - angle = (angle < 0) ? (2 * Math.PI + angle) : angle; - return (angle < Math.PI / 2) || (angle >= 3 * Math.PI / 2); -}; - -/** @private Sets angle based on endAngle or vice versa. */ -pv.Wedge.prototype.buildImplied = function(s) { - if (s.angle == null) s.angle = s.endAngle - s.startAngle; - else if (s.endAngle == null) s.endAngle = s.startAngle + s.angle; - pv.Mark.prototype.buildImplied.call(this, s); -}; - -pv.Wedge.prototype.getShapeCore = function(scenes, index){ - var s = scenes[index]; - return new pv.Shape.Wedge(s.left, s.top, s.innerRadius, s.outerRadius, s.startAngle, s.angle); -}; -/* - * TERMS OF USE - EASING EQUATIONS - * - * Open source under the BSD License. - * - * Copyright 2001 Robert Penner - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the author nor the names of contributors may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -pv.Ease = (function() { - - function reverse(f) { - return function(t) { - return 1 - f(1 - t); - }; - } - - function reflect(f) { - return function(t) { - return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t))); - }; - } - - function poly(e) { - return function(t) { - return t < 0 ? 0 : t > 1 ? 1 : Math.pow(t, e); - } - } - - function sin(t) { - return 1 - Math.cos(t * Math.PI / 2); - } - - function exp(t) { - return t ? Math.pow(2, 10 * (t - 1)) - 0.001 : 0; - } - - function circle(t) { - return -(Math.sqrt(1 - t * t) - 1); - } - - function elastic(a, p) { - var s; - if (!p) p = 0.45; - if (!a || a < 1) { a = 1; s = p / 4; } - else s = p / (2 * Math.PI) * Math.asin(1 / a); - return function(t) { - return t <= 0 || t >= 1 ? t - : -(a * Math.pow(2, 10 * (--t)) * Math.sin((t - s) * (2 * Math.PI) / p)); - }; - } - - function back(s) { - if (!s) s = 1.70158; - return function(t) { - return t * t * ((s + 1) * t - s); - }; - } - - function bounce(t) { - return t < 1 / 2.75 ? 7.5625 * t * t - : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 - : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 - : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; - } - - var quad = poly(2), - cubic = poly(3), - elasticDefault = elastic(), - backDefault = back(); - - var eases = { - "linear": pv.identity, - "quad-in": quad, - "quad-out": reverse(quad), - "quad-in-out": reflect(quad), - "quad-out-in": reflect(reverse(quad)), - "cubic-in": cubic, - "cubic-out": reverse(cubic), - "cubic-in-out": reflect(cubic), - "cubic-out-in": reflect(reverse(cubic)), - "sin-in": sin, - "sin-out": reverse(sin), - "sin-in-out": reflect(sin), - "sin-out-in": reflect(reverse(sin)), - "exp-in": exp, - "exp-out": reverse(exp), - "exp-in-out": reflect(exp), - "exp-out-in": reflect(reverse(exp)), - "circle-in": circle, - "circle-out": reverse(circle), - "circle-in-out": reflect(circle), - "circle-out-in": reflect(reverse(circle)), - "elastic-in": elasticDefault, - "elastic-out": reverse(elasticDefault), - "elastic-in-out": reflect(elasticDefault), - "elastic-out-in": reflect(reverse(elasticDefault)), - "back-in": backDefault, - "back-out": reverse(backDefault), - "back-in-out": reflect(backDefault), - "back-out-in": reflect(reverse(backDefault)), - "bounce-in": bounce, - "bounce-out": reverse(bounce), - "bounce-in-out": reflect(bounce), - "bounce-out-in": reflect(reverse(bounce)) - }; - - pv.ease = function(f) { - return eases[f]; - }; - - return { - reverse: reverse, - reflect: reflect, - linear: function() { return pv.identity; }, - sin: function() { return sin; }, - exp: function() { return exp; }, - circle: function() { return circle; }, - elastic: elastic, - back: back, - bounce: bounce, - poly: poly - }; -})(); -pv.Transition = function(mark) { - var that = this, - ease = pv.ease("cubic-in-out"), - duration = 250, - timer, - onEndCallback; - - var interpolated = { - top: 1, - left: 1, - right: 1, - bottom: 1, - width: 1, - height: 1, - innerRadius: 1, - outerRadius: 1, - radius: 1, - startAngle: 1, - endAngle: 1, - angle: 1, - fillStyle: 1, - strokeStyle: 1, - lineWidth: 1, - eccentricity: 1, - tension: 1, - textAngle: 1, - textStyle: 1, - textMargin: 1 - }; - - var defaults = new pv.Transient(); - - /** @private */ - function ids(marks) { - var map = {}; - for (var i = 0; i < marks.length; i++) { - var mark = marks[i]; - if (mark.id) { - map[mark.id] = mark; - } - } - - return map; - } - - /** @private */ - function interpolateProperty(list, name, before, after) { - var f; - if (name in interpolated) { - var i = pv.Scale.interpolator(before[name], after[name]); - f = function(t) { - before[name] = i(t); - }; - } else { - f = function(t) { - if (t > .5) { - before[name] = after[name]; - } - }; - } - f.next = list.head; - list.head = f; - } - - /** @private */ - function interpolateInstance(list, before, after) { - for (var name in before) { - if (name == "children") continue; // not a property - if (before[name] == after[name]) continue; // unchanged - interpolateProperty(list, name, before, after); - } - if (before.children) { - for (var j = 0; j < before.children.length; j++) { - interpolate(list, before.children[j], after.children[j]); - } - } - } - - /** @private */ - function interpolate(list, before, after) { - var mark = before.mark, - bi = ids(before), - ai = ids(after); - - for (var i = 0; i < before.length; i++) { - var b = before[i], - a = b.id ? ai[b.id] : after[i]; - - b.index = i; - - if (!b.visible) { - continue; - } - - // No after or not after.visible - if (!(a && a.visible)) { - var o = override(before, i, mark.$exit, after); - - /* - * After the transition finishes, we need to do a little cleanup to - * insure that the final state of the scenegraph is consistent with the - * "after" render. For instances that were removed, we need to remove - * them from the scenegraph; for instances that became invisible, we - * need to mark them invisible. See the cleanup method for details. - */ - b.transition = a ? - 2 : - (after.push(o), 1); - a = o; - } - interpolateInstance(list, b, a); - } - - for (var i = 0; i < after.length; i++) { - var a = after[i], - b = a.id ? bi[a.id] : before[i]; - - if (!(b && b.visible) && a.visible) { - var o = override(after, i, mark.$enter, before); - if (!b) - before.push(o); - else - before[b.index] = o; - - interpolateInstance(list, o, a); - } - } - } - - /** @private */ - function override(scene, index, proto, other) { - var s = pv.extend(scene[index]), - m = scene.mark, - r = m.root.scene, - p = (proto || defaults).$properties, - t; - - /* Correct the target reference, if this is an anchor. */ - if (other.target && (t = other.target[other.length])) { - scene = pv.extend(scene); - scene.target = pv.extend(other.target); - scene.target[index] = t; - } - - /* Determine the set of properties to evaluate. */ - var seen = {}; - for (var i = 0; i < p.length; i++) { - seen[p[i].name] = 1; - } - - /* Add to p all optional properties in binds not in proto properties (p) */ - p = m.binds.optional - .filter(function(p) { return !(p.name in seen); }) - .concat(p); - - /* Evaluate the properties and update any implied ones. */ - m.context(scene, index, function() { - this.buildProperties(s, p); - this.buildImplied(s); - }); - - /* Restore the root scene. This should probably be done by context(). */ - m.root.scene = r; - return s; - } - - /** @private */ - function cleanup(scene) { - for (var i = 0, j = 0; i < scene.length; i++) { - var s = scene[i]; - if (s.transition != 1) { - scene[j++] = s; - if (s.transition == 2) s.visible = false; - if (s.children) s.children.forEach(cleanup); - } - } - scene.length = j; - } - - that.ease = function(x) { - return arguments.length - ? (ease = typeof x == "function" ? x : pv.ease(x), that) - : ease; - }; - - that.duration = function(x) { - return arguments.length - ? (duration = Number(x), that) - : duration; - }; - - function doEnd(){ - mark.root.animatingCount--; - - if(onEndCallback){ - var cb = onEndCallback; - onEndCallback = null; - cb(); - } - } - - that.start = function(onEnd) { - onEndCallback = onEnd; - - mark.root.animatingCount++; - - // TODO allow partial rendering - if (mark.parent) { - doEnd(); - throw new Error("Animated partial rendering is not supported."); - } - - try{ - // TODO allow parallel and sequenced transitions - if (mark.$transition) { - mark.$transition.stop(); - } - mark.$transition = that; - - // TODO clearing the scene like this forces total re-build - var i = pv.Mark.prototype.index, - before = mark.scene, - after; - - mark.scene = null; - mark.bind(); - mark.build(); - - after = mark.scene; - mark.scene = before; - - pv.Mark.prototype.index = i; - - var start = Date.now(), - list = {}; - - interpolate(list, before, after); - } catch(ex) { - doEnd(); - throw ex; - } - - timer = setInterval(function() { - var t = Math.max(0, Math.min(1, (Date.now() - start) / duration)), - e = ease(t); - - /* Advance every property of every mark */ - for (var i = list.head ; i ; i = i.next) { - i(e); - } - - if (t == 1) { - cleanup(mark.scene); - that.stop(); - } - pv.Scene.updateAll(before); - }, 24); - }; - - that.stop = function() { - clearInterval(timer); - doEnd(); - }; -}; -pv.Transient = function(mark) { - pv.Mark.call(this); - this.fillStyle(null).strokeStyle(null).textStyle(null); - this.on = function(state) { return mark.on(state); }; -}; - -pv.Transient.prototype = pv.extend(pv.Mark); -/** - * Abstract; not implemented. There is no explicit constructor; this class - * merely serves to document the attributes that are used on particles in - * physics simulations. - * - * @class A weighted particle that can participate in a force simulation. - * - * @name pv.Particle - */ - -/** - * The next particle in the simulation. Particles form a singly-linked list. - * - * @field - * @type pv.Particle - * @name pv.Particle.prototype.next - */ - -/** - * The x-position of the particle. - * - * @field - * @type number - * @name pv.Particle.prototype.x - */ - -/** - * The y-position of the particle. - * - * @field - * @type number - * @name pv.Particle.prototype.y - */ - -/** - * The x-velocity of the particle. - * - * @field - * @type number - * @name pv.Particle.prototype.vx - */ - -/** - * The y-velocity of the particle. - * - * @field - * @type number - * @name pv.Particle.prototype.vy - */ - -/** - * The x-position of the particle at -dt. - * - * @field - * @type number - * @name pv.Particle.prototype.px - */ - -/** - * The y-position of the particle at -dt. - * - * @field - * @type number - * @name pv.Particle.prototype.py - */ - -/** - * The x-force on the particle. - * - * @field - * @type number - * @name pv.Particle.prototype.fx - */ - -/** - * The y-force on the particle. - * - * @field - * @type number - * @name pv.Particle.prototype.fy - */ -/** - * Constructs a new empty simulation. - * - * @param {array} particles - * @returns {pv.Simulation} a new simulation for the specified particles. - * @see pv.Simulation - */ -pv.simulation = function(particles) { - return new pv.Simulation(particles); -}; - -/** - * Constructs a new simulation for the specified particles. - * - * @class Represents a particle simulation. Particles are massive points in - * two-dimensional space. Forces can be applied to these particles, causing them - * to move. Constraints can also be applied to restrict particle movement, for - * example, constraining particles to a fixed position, or simulating collision - * between circular particles with area. - * - *

The simulation uses Position Verlet - * integration, due to the ease with which geometric constraints can be - * implemented. For each time step, Verlet integration is performed, new forces - * are accumulated, and then constraints are applied. - * - *

The simulation makes two simplifying assumptions: all particles are - * equal-mass, and the time step of the simulation is fixed. It would be easy to - * incorporate variable-mass particles as a future enhancement. Variable time - * steps are also possible, but are likely to introduce instability in the - * simulation. - * - *

This class can be used directly to simulate particle interaction. - * Alternatively, for network diagrams, see {@link pv.Layout.Force}. - * - * @param {array} particles an array of {@link pv.Particle}s to simulate. - * @see pv.Layout.Force - * @see pv.Force - * @see pv.Constraint - */ -pv.Simulation = function(particles) { - for (var i = 0; i < particles.length; i++) this.particle(particles[i]); -}; - -/** - * The particles in the simulation. Particles are stored as a linked list; this - * field represents the first particle in the simulation. - * - * @field - * @type pv.Particle - * @name pv.Simulation.prototype.particles - */ - -/** - * The forces in the simulation. Forces are stored as a linked list; this field - * represents the first force in the simulation. - * - * @field - * @type pv.Force - * @name pv.Simulation.prototype.forces - */ - -/** - * The constraints in the simulation. Constraints are stored as a linked list; - * this field represents the first constraint in the simulation. - * - * @field - * @type pv.Constraint - * @name pv.Simulation.prototype.constraints - */ - -/** - * Adds the specified particle to the simulation. - * - * @param {pv.Particle} p the new particle. - * @returns {pv.Simulation} this. - */ -pv.Simulation.prototype.particle = function(p) { - p.next = this.particles; - /* Default velocities and forces to zero if unset. */ - if (isNaN(p.px)) p.px = p.x; - if (isNaN(p.py)) p.py = p.y; - if (isNaN(p.fx)) p.fx = 0; - if (isNaN(p.fy)) p.fy = 0; - this.particles = p; - return this; -}; - -/** - * Adds the specified force to the simulation. - * - * @param {pv.Force} f the new force. - * @returns {pv.Simulation} this. - */ -pv.Simulation.prototype.force = function(f) { - f.next = this.forces; - this.forces = f; - return this; -}; - -/** - * Adds the specified constraint to the simulation. - * - * @param {pv.Constraint} c the new constraint. - * @returns {pv.Simulation} this. - */ -pv.Simulation.prototype.constraint = function(c) { - c.next = this.constraints; - this.constraints = c; - return this; -}; - -/** - * Apply constraints, and then set the velocities to zero. - * - * @returns {pv.Simulation} this. - */ -pv.Simulation.prototype.stabilize = function(n) { - var c; - if (!arguments.length) n = 3; // TODO use cooling schedule - for (var i = 0; i < n; i++) { - var q = new pv.Quadtree(this.particles); - for (c = this.constraints; c; c = c.next) c.apply(this.particles, q); - } - for (var p = this.particles; p; p = p.next) { - p.px = p.x; - p.py = p.y; - } - return this; -}; - -/** - * Advances the simulation one time-step. - */ -pv.Simulation.prototype.step = function() { - var p, f, c; - - /* - * Assumptions: - * - The mass (m) of every particles is 1. - * - The time step (dt) is 1. - */ - - /* Position Verlet integration. */ - for (p = this.particles; p; p = p.next) { - var px = p.px, py = p.py; - p.px = p.x; - p.py = p.y; - p.x += p.vx = ((p.x - px) + p.fx); - p.y += p.vy = ((p.y - py) + p.fy); - } - - /* Apply constraints, then accumulate new forces. */ - var q = new pv.Quadtree(this.particles); - for (c = this.constraints; c; c = c.next) c.apply(this.particles, q); - for (p = this.particles; p; p = p.next) p.fx = p.fy = 0; - for (f = this.forces; f; f = f.next) f.apply(this.particles, q); -}; -/** - * Constructs a new quadtree for the specified array of particles. - * - * @class Represents a quadtree: a two-dimensional recursive spatial - * subdivision. This particular implementation uses square partitions, dividing - * each square into four equally-sized squares. Each particle exists in a unique - * node; if multiple particles are in the same position, some particles may be - * stored on internal nodes rather than leaf nodes. - * - *

This quadtree can be used to accelerate various spatial operations, such - * as the Barnes-Hut approximation for computing n-body forces, or collision - * detection. - * - * @see pv.Force.charge - * @see pv.Constraint.collision - * @param {pv.Particle} particles the linked list of particles. - */ -pv.Quadtree = function(particles) { - var p; - - /* Compute bounds. */ - var x1 = Number.POSITIVE_INFINITY, y1 = x1, - x2 = Number.NEGATIVE_INFINITY, y2 = x2; - for (p = particles; p; p = p.next) { - if (p.x < x1) x1 = p.x; - if (p.y < y1) y1 = p.y; - if (p.x > x2) x2 = p.x; - if (p.y > y2) y2 = p.y; - } - - /* Squarify the bounds. */ - var dx = x2 - x1, dy = y2 - y1; - if (dx > dy) y2 = y1 + dx; - else x2 = x1 + dy; - this.xMin = x1; - this.yMin = y1; - this.xMax = x2; - this.yMax = y2; - - /** - * @ignore Recursively inserts the specified particle p at the node - * n or one of its descendants. The bounds are defined by [x1, - * x2] and [y1, y2]. - */ - function insert(n, p, x1, y1, x2, y2) { - if (isNaN(p.x) || isNaN(p.y)) return; // ignore invalid particles - if (n.leaf) { - if (n.p) { - /* - * If the particle at this leaf node is at the same position as the new - * particle we are adding, we leave the particle associated with the - * internal node while adding the new particle to a child node. This - * avoids infinite recursion. - */ - if ((Math.abs(n.p.x - p.x) + Math.abs(n.p.y - p.y)) < .01) { - insertChild(n, p, x1, y1, x2, y2); - } else { - var v = n.p; - n.p = null; - insertChild(n, v, x1, y1, x2, y2); - insertChild(n, p, x1, y1, x2, y2); - } - } else { - n.p = p; - } - } else { - insertChild(n, p, x1, y1, x2, y2); - } - } - - /** - * @ignore Recursively inserts the specified particle p into a - * descendant of node n. The bounds are defined by [x1, - * x2] and [y1, y2]. - */ - function insertChild(n, p, x1, y1, x2, y2) { - /* Compute the split point, and the quadrant in which to insert p. */ - var sx = (x1 + x2) * .5, - sy = (y1 + y2) * .5, - right = p.x >= sx, - bottom = p.y >= sy; - - /* Recursively insert into the child node. */ - n.leaf = false; - switch ((bottom << 1) + right) { - case 0: n = n.c1 || (n.c1 = new pv.Quadtree.Node()); break; - case 1: n = n.c2 || (n.c2 = new pv.Quadtree.Node()); break; - case 2: n = n.c3 || (n.c3 = new pv.Quadtree.Node()); break; - case 3: n = n.c4 || (n.c4 = new pv.Quadtree.Node()); break; - } - - /* Update the bounds as we recurse. */ - if (right) x1 = sx; else x2 = sx; - if (bottom) y1 = sy; else y2 = sy; - insert(n, p, x1, y1, x2, y2); - } - - /* Insert all particles. */ - this.root = new pv.Quadtree.Node(); - for (p = particles; p; p = p.next) insert(this.root, p, x1, y1, x2, y2); -}; - -/** - * The root node of the quadtree. - * - * @type pv.Quadtree.Node - * @name pv.Quadtree.prototype.root - */ - -/** - * The minimum x-coordinate value of all contained particles. - * - * @type number - * @name pv.Quadtree.prototype.xMin - */ - -/** - * The maximum x-coordinate value of all contained particles. - * - * @type number - * @name pv.Quadtree.prototype.xMax - */ - -/** - * The minimum y-coordinate value of all contained particles. - * - * @type number - * @name pv.Quadtree.prototype.yMin - */ - -/** - * The maximum y-coordinate value of all contained particles. - * - * @type number - * @name pv.Quadtree.prototype.yMax - */ - -/** - * Constructs a new node. - * - * @class A node in a quadtree. - * - * @see pv.Quadtree - */ -pv.Quadtree.Node = function() { - /* - * Prepopulating all attributes significantly increases performance! Also, - * letting the language interpreter manage garbage collection was moderately - * faster than creating a cache pool. - */ - this.leaf = true; - this.c1 = null; - this.c2 = null; - this.c3 = null; - this.c4 = null; - this.p = null; -}; - -/** - * True if this node is a leaf node; i.e., it has no children. Note that both - * leaf nodes and non-leaf (internal) nodes may have associated particles. If - * this is a non-leaf node, then at least one of {@link #c1}, {@link #c2}, - * {@link #c3} or {@link #c4} is guaranteed to be non-null. - * - * @type boolean - * @name pv.Quadtree.Node.prototype.leaf - */ - -/** - * The particle associated with this node, if any. - * - * @type pv.Particle - * @name pv.Quadtree.Node.prototype.p - */ - -/** - * The child node for the second quadrant, if any. - * - * @type pv.Quadtree.Node - * @name pv.Quadtree.Node.prototype.c2 - */ - -/** - * The child node for the third quadrant, if any. - * - * @type pv.Quadtree.Node - * @name pv.Quadtree.Node.prototype.c3 - */ - -/** - * The child node for the fourth quadrant, if any. - * - * @type pv.Quadtree.Node - * @name pv.Quadtree.Node.prototype.c4 - */ -/** - * Abstract; see an implementing class. - * - * @class Represents a force that acts on particles. Note that this interface - * does not specify how to bind a force to specific particles; in general, - * forces are applied globally to all particles. However, some forces may be - * applied to specific particles or between particles, such as spring forces, - * through additional specialization. - * - * @see pv.Simulation - * @see pv.Particle - * @see pv.Force.charge - * @see pv.Force.drag - * @see pv.Force.spring - */ -pv.Force = {}; - -/** - * Applies this force to the specified particles. - * - * @function - * @name pv.Force.prototype.apply - * @param {pv.Particle} particles particles to which to apply this force. - * @param {pv.Quadtree} q a quadtree for spatial acceleration. - */ -/** - * Constructs a new charge force, with an optional charge constant. The charge - * constant can be negative for repulsion (e.g., particles with electrical - * charge of equal sign), or positive for attraction (e.g., massive particles - * with mutual gravity). The default charge constant is -40. - * - * @class An n-body force, as defined by Coulomb's law or Newton's law of - * gravitation, inversely proportional to the square of the distance between - * particles. Note that the force is independent of the mass of the - * associated particles, and that the particles do not have charges of varying - * magnitude; instead, the attraction or repulsion of all particles is globally - * specified as the charge {@link #constant}. - * - *

This particular implementation uses the Barnes-Hut algorithm. For details, - * see "A - * hierarchical O(N log N) force-calculation algorithm", J. Barnes & - * P. Hut, Nature 1986. - * - * @name pv.Force.charge - * @param {number} [k] the charge constant. - */ -pv.Force.charge = function(k) { - var min = 2, // minimum distance at which to observe forces - min1 = 1 / min, - max = 500, // maximum distance at which to observe forces - max1 = 1 / max, - theta = .9, // Barnes-Hut theta approximation constant - force = {}; - - if (!arguments.length) k = -40; // default charge constant (repulsion) - - /** - * Sets or gets the charge constant. If an argument is specified, it is the - * new charge constant. The charge constant can be negative for repulsion - * (e.g., particles with electrical charge of equal sign), or positive for - * attraction (e.g., massive particles with mutual gravity). The default - * charge constant is -40. - * - * @function - * @name pv.Force.charge.prototype.constant - * @param {number} x the charge constant. - * @returns {pv.Force.charge} this. - */ - force.constant = function(x) { - if (arguments.length) { - k = Number(x); - return force; - } - return k; - }; - - /** - * Sets or gets the domain; specifies the minimum and maximum domain within - * which charge forces are applied. A minimum distance threshold avoids - * applying forces that are two strong (due to granularity of the simulation's - * numeric integration). A maximum distance threshold improves performance by - * skipping force calculations for particles that are far apart. - * - *

The default domain is [2, 500]. - * - * @function - * @name pv.Force.charge.prototype.domain - * @param {number} a - * @param {number} b - * @returns {pv.Force.charge} this. - */ - force.domain = function(a, b) { - if (arguments.length) { - min = Number(a); - min1 = 1 / min; - max = Number(b); - max1 = 1 / max; - return force; - } - return [min, max]; - }; - - /** - * Sets or gets the Barnes-Hut approximation factor. The Barnes-Hut - * approximation criterion is the ratio of the size of the quadtree node to - * the distance from the point to the node's center of mass is beneath some - * threshold. - * - * @function - * @name pv.Force.charge.prototype.theta - * @param {number} x the new Barnes-Hut approximation factor. - * @returns {pv.Force.charge} this. - */ - force.theta = function(x) { - if (arguments.length) { - theta = Number(x); - return force; - } - return theta; - }; - - /** - * @ignore Recursively computes the center of charge for each node in the - * quadtree. This is equivalent to the center of mass, assuming that all - * particles have unit weight. - */ - function accumulate(n) { - var cx = 0, cy = 0; - n.cn = 0; - function accumulateChild(c) { - accumulate(c); - n.cn += c.cn; - cx += c.cn * c.cx; - cy += c.cn * c.cy; - } - if (!n.leaf) { - if (n.c1) accumulateChild(n.c1); - if (n.c2) accumulateChild(n.c2); - if (n.c3) accumulateChild(n.c3); - if (n.c4) accumulateChild(n.c4); - } - if (n.p) { - n.cn += k; - cx += k * n.p.x; - cy += k * n.p.y; - } - n.cx = cx / n.cn; - n.cy = cy / n.cn; - } - - /** - * @ignore Recursively computes forces on the given particle using the given - * quadtree node. The Barnes-Hut approximation criterion is the ratio of the - * size of the quadtree node to the distance from the point to the node's - * center of mass is beneath some threshold. - */ - function forces(n, p, x1, y1, x2, y2) { - var dx = n.cx - p.x, - dy = n.cy - p.y, - dn = 1 / Math.sqrt(dx * dx + dy * dy); - - /* Barnes-Hut criterion. */ - if ((n.leaf && (n.p != p)) || ((x2 - x1) * dn < theta)) { - if (dn < max1) return; - if (dn > min1) dn = min1; - var kc = n.cn * dn * dn * dn, - fx = dx * kc, - fy = dy * kc; - p.fx += fx; - p.fy += fy; - } else if (!n.leaf) { - var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5; - if (n.c1) forces(n.c1, p, x1, y1, sx, sy); - if (n.c2) forces(n.c2, p, sx, y1, x2, sy); - if (n.c3) forces(n.c3, p, x1, sy, sx, y2); - if (n.c4) forces(n.c4, p, sx, sy, x2, y2); - if (dn < max1) return; - if (dn > min1) dn = min1; - if (n.p && (n.p != p)) { - var kc = k * dn * dn * dn, - fx = dx * kc, - fy = dy * kc; - p.fx += fx; - p.fy += fy; - } - } - } - - /** - * Applies this force to the specified particles. The force is applied between - * all pairs of particles within the domain, using the specified quadtree to - * accelerate n-body force calculation using the Barnes-Hut approximation - * criterion. - * - * @function - * @name pv.Force.charge.prototype.apply - * @param {pv.Particle} particles particles to which to apply this force. - * @param {pv.Quadtree} q a quadtree for spatial acceleration. - */ - force.apply = function(particles, q) { - accumulate(q.root); - for (var p = particles; p; p = p.next) { - forces(q.root, p, q.xMin, q.yMin, q.xMax, q.yMax); - } - }; - - return force; -}; -/** - * Constructs a new drag force with the specified constant. - * - * @class Implements a drag force, simulating friction. The drag force is - * applied in the opposite direction of the particle's velocity. Since Position - * Verlet integration does not track velocities explicitly, the error term with - * this estimate of velocity is fairly high, so the drag force may be - * inaccurate. - * - * @extends pv.Force - * @param {number} k the drag constant. - * @see #constant - */ -pv.Force.drag = function(k) { - var force = {}; - - if (!arguments.length) k = .1; // default drag constant - - /** - * Sets or gets the drag constant, in the range [0,1]. The default drag - * constant is 0.1. The drag forces scales linearly with the particle's - * velocity based on the given drag constant. - * - * @function - * @name pv.Force.drag.prototype.constant - * @param {number} x the new drag constant. - * @returns {pv.Force.drag} this, or the current drag constant. - */ - force.constant = function(x) { - if (arguments.length) { k = x; return force; } - return k; - }; - - /** - * Applies this force to the specified particles. - * - * @function - * @name pv.Force.drag.prototype.apply - * @param {pv.Particle} particles particles to which to apply this force. - */ - force.apply = function(particles) { - if (k) for (var p = particles; p; p = p.next) { - p.fx -= k * p.vx; - p.fy -= k * p.vy; - } - }; - - return force; -}; -/** - * Constructs a new spring force with the specified constant. The links - * associated with this spring force must be specified before the spring force - * can be applied. - * - * @class Implements a spring force, per Hooke's law. The spring force can be - * configured with a tension constant, rest length, and damping factor. The - * tension and damping will automatically be normalized using the inverse square - * root of the maximum link degree of attached nodes; this makes springs weaker - * between nodes of high link degree. - * - *

Unlike other forces (such as charge and drag forces) which may be applied - * globally, spring forces are only applied between linked particles. Therefore, - * an array of links must be specified before this force can be applied; the - * links should be an array of {@link pv.Layout.Network.Link}s. See also - * {@link pv.Layout.Force} for an example of using spring and charge forces for - * network layout. - * - * @extends pv.Force - * @param {number} k the spring constant. - * @see #constant - * @see #links - */ -pv.Force.spring = function(k) { - var d = .1, // default damping factor - l = 20, // default rest length - links, // links on which to apply spring forces - kl, // per-spring normalization - force = {}; - - if (!arguments.length) k = .1; // default spring constant (tension) - - /** - * Sets or gets the links associated with this spring force. Unlike other - * forces (such as charge and drag forces) which may be applied globally, - * spring forces are only applied between linked particles. Therefore, an - * array of links must be specified before this force can be applied; the - * links should be an array of {@link pv.Layout.Network.Link}s. - * - * @function - * @name pv.Force.spring.prototype.links - * @param {array} x the new array of links. - * @returns {pv.Force.spring} this, or the current array of links. - */ - force.links = function(x) { - if (arguments.length) { - links = x; - kl = x.map(function(l) { - return 1 / Math.sqrt(Math.max( - l.sourceNode.linkDegree, - l.targetNode.linkDegree)); - }); - return force; - } - return links; - }; - - /** - * Sets or gets the spring constant. The default value is 0.1; greater values - * will result in stronger tension. The spring tension is automatically - * normalized using the inverse square root of the maximum link degree of - * attached nodes. - * - * @function - * @name pv.Force.spring.prototype.constant - * @param {number} x the new spring constant. - * @returns {pv.Force.spring} this, or the current spring constant. - */ - force.constant = function(x) { - if (arguments.length) { - k = Number(x); - return force; - } - return k; - }; - - /** - * The spring damping factor, in the range [0,1]. Damping functions - * identically to drag forces, damping spring bounciness by applying a force - * in the opposite direction of attached nodes' velocities. The default value - * is 0.1. The spring damping is automatically normalized using the inverse - * square root of the maximum link degree of attached nodes. - * - * @function - * @name pv.Force.spring.prototype.damping - * @param {number} x the new spring damping factor. - * @returns {pv.Force.spring} this, or the current spring damping factor. - */ - force.damping = function(x) { - if (arguments.length) { - d = Number(x); - return force; - } - return d; - }; - - /** - * The spring rest length. The default value is 20 pixels. - * - * @function - * @name pv.Force.spring.prototype.length - * @param {number} x the new spring rest length. - * @returns {pv.Force.spring} this, or the current spring rest length. - */ - force.length = function(x) { - if (arguments.length) { - l = Number(x); - return force; - } - return l; - }; - - /** - * Applies this force to the specified particles. - * - * @function - * @name pv.Force.spring.prototype.apply - * @param {pv.Particle} particles particles to which to apply this force. - */ - force.apply = function(particles) { - for (var i = 0; i < links.length; i++) { - var a = links[i].sourceNode, - b = links[i].targetNode, - dx = a.x - b.x, - dy = a.y - b.y, - dn = Math.sqrt(dx * dx + dy * dy), - dd = dn ? (1 / dn) : 1, - ks = k * kl[i], // normalized tension - kd = d * kl[i], // normalized damping - kk = (ks * (dn - l) + kd * (dx * (a.vx - b.vx) + dy * (a.vy - b.vy)) * dd) * dd, - fx = -kk * (dn ? dx : (.01 * (.5 - Math.random()))), - fy = -kk * (dn ? dy : (.01 * (.5 - Math.random()))); - a.fx += fx; - a.fy += fy; - b.fx -= fx; - b.fy -= fy; - } - }; - - return force; -}; -/** - * Abstract; see an implementing class. - * - * @class Represents a constraint that acts on particles. Note that this - * interface does not specify how to bind a constraint to specific particles; in - * general, constraints are applied globally to all particles. However, some - * constraints may be applied to specific particles or between particles, such - * as position constraints, through additional specialization. - * - * @see pv.Simulation - * @see pv.Particle - * @see pv.Constraint.bound - * @see pv.Constraint.collision - * @see pv.Constraint.position - */ -pv.Constraint = {}; - -/** - * Applies this constraint to the specified particles. - * - * @function - * @name pv.Constraint.prototype.apply - * @param {pv.Particle} particles particles to which to apply this constraint. - * @param {pv.Quadtree} q a quadtree for spatial acceleration. - * @returns {pv.Constraint} this. - */ -/** - * Constructs a new collision constraint. The default search radius is 10, and - * the default repeat count is 1. A radius function must be specified to compute - * the radius of particles. - * - * @class Constraints circles to avoid overlap. Each particle is treated as a - * circle, with the radius of the particle computed using a specified function. - * For example, if the particle has an r attribute storing the radius, - * the radius function(d) d.r specifies a collision constraint using - * this radius. The radius function is passed each {@link pv.Particle} as the - * first argument. - * - *

To accelerate collision detection, this implementation uses a quadtree and - * a search radius. The search radius is computed as the maximum radius of all - * particles in the simulation. - * - * @see pv.Constraint - * @param {function} radius the radius function. - */ -pv.Constraint.collision = function(radius) { - var n = 1, // number of times to repeat the constraint - r1, - px1, - py1, - px2, - py2, - constraint = {}; - - if (!arguments.length) r1 = 10; // default search radius - - /** - * Sets or gets the repeat count. If the repeat count is greater than 1, the - * constraint will be applied repeatedly; this is a form of the Gauss-Seidel - * method for constraints relaxation. Repeating the collision constraint makes - * the constraint have more of an effect when there is a potential for many - * co-occurring collisions. - * - * @function - * @name pv.Constraint.collision.prototype.repeat - * @param {number} x the number of times to repeat this constraint. - * @returns {pv.Constraint.collision} this. - */ - constraint.repeat = function(x) { - if (arguments.length) { - n = Number(x); - return constraint; - } - return n; - }; - - /** @private */ - function constrain(n, p, x1, y1, x2, y2) { - if (!n.leaf) { - var sx = (x1 + x2) * .5, - sy = (y1 + y2) * .5, - top = sy > py1, - bottom = sy < py2, - left = sx > px1, - right = sx < px2; - if (top) { - if (n.c1 && left) constrain(n.c1, p, x1, y1, sx, sy); - if (n.c2 && right) constrain(n.c2, p, sx, y1, x2, sy); - } - if (bottom) { - if (n.c3 && left) constrain(n.c3, p, x1, sy, sx, y2); - if (n.c4 && right) constrain(n.c4, p, sx, sy, x2, y2); - } - } - if (n.p && (n.p != p)) { - var dx = p.x - n.p.x, - dy = p.y - n.p.y, - l = Math.sqrt(dx * dx + dy * dy), - d = r1 + radius(n.p); - if (l < d) { - var k = (l - d) / l * .5; - dx *= k; - dy *= k; - p.x -= dx; - p.y -= dy; - n.p.x += dx; - n.p.y += dy; - } - } - } - - /** - * Applies this constraint to the specified particles. - * - * @function - * @name pv.Constraint.collision.prototype.apply - * @param {pv.Particle} particles particles to which to apply this constraint. - * @param {pv.Quadtree} q a quadtree for spatial acceleration. - */ - constraint.apply = function(particles, q) { - var p, r, max = -Infinity; - for (p = particles; p; p = p.next) { - r = radius(p); - if (r > max) max = r; - } - for (var i = 0; i < n; i++) { - for (p = particles; p; p = p.next) { - r = (r1 = radius(p)) + max; - px1 = p.x - r; - px2 = p.x + r; - py1 = p.y - r; - py2 = p.y + r; - constrain(q.root, p, q.xMin, q.yMin, q.xMax, q.yMax); - } - } - }; - - return constraint; -}; -/** - * Constructs a default position constraint using the fix attribute. - * An optional position function can be specified to determine how the fixed - * position per-particle is determined. - * - * @class Constraints particles to a fixed position. The fixed position per - * particle is determined using a given position function, which defaults to - * function(d) d.fix. - * - *

If the position function returns null, then no position constraint is - * applied to the given particle. Otherwise, the particle's position is set to - * the returned position, as expressed by a {@link pv.Vector}. (Note: the - * position does not need to be an instance of pv.Vector, but simply an - * object with x and y attributes.) - * - *

This constraint also supports a configurable alpha parameter, which - * defaults to 1. If the alpha parameter is in the range [0,1], then rather than - * setting the particle's new position directly to the position returned by the - * supplied position function, the particle's position is interpolated towards - * the fixed position. This results is a smooth (exponential) drift towards the - * fixed position, which can increase the stability of the physics simulation. - * In addition, the alpha parameter can be decayed over time, relaxing the - * position constraint, which helps to stabilize on an optimal solution. - * - * @param {function} [f] the position function. - */ -pv.Constraint.position = function(f) { - var a = 1, // default alpha - constraint = {}; - - if (!arguments.length) /** @ignore */ f = function(p) { return p.fix; }; - - /** - * Sets or gets the alpha parameter for position interpolation. If the alpha - * parameter is in the range [0,1], then rather than setting the particle's - * new position directly to the position returned by the supplied position - * function, the particle's position is interpolated towards the fixed - * position. - * - * @function - * @name pv.Constraint.position.prototype.alpha - * @param {number} x the new alpha parameter, in the range [0,1]. - * @returns {pv.Constraint.position} this. - */ - constraint.alpha = function(x) { - if (arguments.length) { - a = Number(x); - return constraint; - } - return a; - }; - - /** - * Applies this constraint to the specified particles. - * - * @function - * @name pv.Constraint.position.prototype.apply - * @param {pv.Particle} particles particles to which to apply this constraint. - */ - constraint.apply = function(particles) { - for (var p = particles; p; p = p.next) { - var v = f(p); - if (v) { - p.x += (v.x - p.x) * a; - p.y += (v.y - p.y) * a; - p.fx = p.fy = p.vx = p.vy = 0; - } - } - }; - - return constraint; -}; -/** - * Constructs a new bound constraint. Before the constraint can be used, the - * {@link #x} and {@link #y} methods must be call to specify the bounds. - * - * @class Constrains particles to within fixed rectangular bounds. For example, - * this constraint can be used to constrain particles in a physics simulation - * within the bounds of an enclosing panel. - * - *

Note that the current implementation treats particles as points, with no - * area. If the particles are rendered as dots, be sure to include some - * additional padding to inset the bounds such that the edges of the dots do not - * get clipped by the panel bounds. If the particles have different radii, this - * constraint would need to be extended using a radius function, similar to - * {@link pv.Constraint.collision}. - * - * @see pv.Layout.Force - * @extends pv.Constraint - */ -pv.Constraint.bound = function() { - var constraint = {}, - x, - y; - - /** - * Sets or gets the bounds on the x-coordinate. - * - * @function - * @name pv.Constraint.bound.prototype.x - * @param {number} min the minimum allowed x-coordinate. - * @param {number} max the maximum allowed x-coordinate. - * @returns {pv.Constraint.bound} this. - */ - constraint.x = function(min, max) { - if (arguments.length) { - x = {min: Math.min(min, max), max: Math.max(min, max)}; - return this; - } - return x; - }; - - /** - * Sets or gets the bounds on the y-coordinate. - * - * @function - * @name pv.Constraint.bound.prototype.y - * @param {number} min the minimum allowed y-coordinate. - * @param {number} max the maximum allowed y-coordinate. - * @returns {pv.Constraint.bound} this. - */ - constraint.y = function(min, max) { - if (arguments.length) { - y = {min: Math.min(min, max), max: Math.max(min, max)}; - return this; - } - return y; - }; - - /** - * Applies this constraint to the specified particles. - * - * @function - * @name pv.Constraint.bound.prototype.apply - * @param {pv.Particle} particles particles to which to apply this constraint. - */ - constraint.apply = function(particles) { - if (x) for (var p = particles; p; p = p.next) { - p.x = p.x < x.min ? x.min : (p.x > x.max ? x.max : p.x); - } - if (y) for (var p = particles; p; p = p.next) { - p.y = p.y < y.min ? y.min : (p.y > y.max ? y.max : p.y); - } - }; - - return constraint; -}; -/** - * Constructs a new, empty layout with default properties. Layouts are not - * typically constructed directly; instead, a concrete subclass is added to an - * existing panel via {@link pv.Mark#add}. - * - * @class Represents an abstract layout, encapsulating a visualization technique - * such as a streamgraph or treemap. Layouts are themselves containers, - * extending from {@link pv.Panel}, and defining a set of mark prototypes as - * children. These mark prototypes provide default properties that together - * implement the given visualization technique. - * - *

Layouts do not initially contain any marks; any exported marks (such as a - * network layout's link and node) are intended to be used as - * prototypes. By adding a concrete mark, such as a {@link pv.Bar}, to the - * appropriate mark prototype, the mark is added to the layout and inherits the - * given properties. This approach allows further customization of the layout, - * either by choosing a different mark type to add, or more simply by overriding - * some of the layout's defined properties. - * - *

Each concrete layout, such as treemap or circle-packing, has different - * behavior and may export different mark prototypes, depending on what marks - * are typically needed to render the desired visualization. Therefore it is - * important to understand how each layout is structured, such that the provided - * mark prototypes are used appropriately. - * - *

In addition to the mark prototypes, layouts may define custom properties - * that affect the overall behavior of the layout. For example, a treemap layout - * might use a property to specify which layout algorithm to use. These - * properties are just like other mark properties, and can be defined as - * constants or as functions. As with panels, the data property can be used to - * replicate layouts, and properties can be defined to in terms of layout data. - * - * @extends pv.Panel - */ -pv.Layout = function() { - pv.Panel.call(this); -}; - -pv.Layout.prototype = pv.extend(pv.Panel); - -/** - * @private Defines a local property with the specified name and cast. Note that - * although the property method is only defined locally, the cast function is - * global, which is necessary since properties are inherited! - * - * @param {string} name the property name. - * @param {function} [cast] the cast function for this property. - */ -pv.Layout.prototype.property = pv.Mark.prototype.localProperty; -/** - * Constructs a new, empty network layout. Layouts are not typically constructed - * directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Represents an abstract layout for network diagrams. This class - * provides the basic structure for both node-link diagrams (such as - * force-directed graph layout) and space-filling network diagrams (such as - * sunbursts and treemaps). Note that "network" here is a general term that - * includes hierarchical structures; a tree is represented using links from - * child to parent. - * - *

Network layouts require the graph data structure to be defined using two - * properties:

    - * - *
  • nodes - an array of objects representing nodes. Objects in this - * array must conform to the {@link pv.Layout.Network.Node} interface; which is - * to say, be careful to avoid naming collisions with automatic attributes such - * as index and linkDegree. If the nodes property is defined - * as an array of primitives, such as numbers or strings, these primitives are - * automatically wrapped in an object; the resulting object's nodeValue - * attribute points to the original primitive value. - * - *

  • links - an array of objects representing links. Objects in - * this array must conform to the {@link pv.Layout.Network.Link} interface; at a - * minimum, either source and target indexes or - * sourceNode and targetNode references must be set. Note that - * if the links property is defined after the nodes property, the links can be - * defined in terms of this.nodes(). - * - *
- * - *

Three standard mark prototypes are provided:

    - * - *
  • node - for rendering nodes; typically a {@link pv.Dot}. The node - * mark is added directly to the layout, with the data property defined via the - * layout's nodes property. Properties such as strokeStyle and - * fillStyle can be overridden to compute properties from node data - * dynamically. - * - *

  • link - for rendering links; typically a {@link pv.Line}. The - * link mark is added to a child panel, whose data property is defined as - * layout's links property. The link's data property is then a - * two-element array of the source node and target node. Thus, poperties such as - * strokeStyle and fillStyle can be overridden to compute - * properties from either the node data (the first argument) or the link data - * (the second argument; the parent panel data) dynamically. - * - *

  • label - for rendering node labels; typically a - * {@link pv.Label}. The label mark is added directly to the layout, with the - * data property defined via the layout's nodes property. Properties - * such as strokeStyle and fillStyle can be overridden to - * compute properties from node data dynamically. - * - *
Note that some network implementations may not support all three - * standard mark prototypes; for example, space-filling hierarchical layouts - * typically do not use a link prototype, as the parent-child links are - * implied by the structure of the space-filling node marks. Check the - * specific network layout for implementation details. - * - *

Network layout properties, including nodes and links, - * are typically cached rather than re-evaluated with every call to render. This - * is a performance optimization, as network layout algorithms can be - * expensive. If the network structure changes, call {@link #reset} to clear the - * cache before rendering. Note that although the network layout properties are - * cached, child mark properties, such as the marks used to render the nodes and - * links, are not. Therefore, non-structural changes to the network - * layout, such as changing the color of a mark on mouseover, do not need to - * reset the layout. - * - * @see pv.Layout.Hierarchy - * @see pv.Layout.Force - * @see pv.Layout.Matrix - * @see pv.Layout.Arc - * @see pv.Layout.Rollup - * @extends pv.Layout - */ -pv.Layout.Network = function() { - pv.Layout.call(this); - var that = this; - - /* @private Version tracking to cache layout state, improving performance. */ - this.$id = pv.id(); - - /** - * The node prototype. This prototype is intended to be used with a Dot mark - * in conjunction with the link prototype. - * - * @type pv.Mark - * @name pv.Layout.Network.prototype.node - */ - (this.node = new pv.Mark() - .data(function() { return that.nodes(); }) - .strokeStyle("#1f77b4") - .fillStyle("#fff") - .left(function(n) { return n.x; }) - .top(function(n) { return n.y; })).parent = this; - - /** - * The link prototype, which renders edges between source nodes and target - * nodes. This prototype is intended to be used with a Line mark in - * conjunction with the node prototype. - * - * @type pv.Mark - * @name pv.Layout.Network.prototype.link - */ - this.link = new pv.Mark() - .extend(this.node) - .data(function(p) { return [p.sourceNode, p.targetNode]; }) - .fillStyle(null) - .lineWidth(function(d, p) { return p.linkValue * 1.5; }) - .strokeStyle("rgba(0,0,0,.2)"); - - this.link.add = function(type) { - return that.add(pv.Panel) - .data(function() { return that.links(); }) - .add(type) - .extend(this); - }; - - /** - * The node label prototype, which renders the node name adjacent to the node. - * This prototype is provided as an alternative to using the anchor on the - * node mark; it is primarily intended to be used with radial node-link - * layouts, since it provides a convenient mechanism to set the text angle. - * - * @type pv.Mark - * @name pv.Layout.Network.prototype.label - */ - (this.label = new pv.Mark() - .extend(this.node) - .textMargin(7) - .textBaseline("middle") - .text(function(n) { return n.nodeName || n.nodeValue; }) - .textAngle(function(n) { - var a = n.midAngle; - return pv.Wedge.upright(a) ? a : (a + Math.PI); - }) - .textAlign(function(n) { - return pv.Wedge.upright(n.midAngle) ? "left" : "right"; - })).parent = this; -}; - -/** - * @class Represents a node in a network layout. There is no explicit - * constructor; this class merely serves to document the attributes that are - * used on nodes in network layouts. (Note that hierarchical nodes place - * additional requirements on node representation, vis {@link pv.Dom.Node}.) - * - * @see pv.Layout.Network - * @name pv.Layout.Network.Node - */ - -/** - * The node index, zero-based. This attribute is populated automatically based - * on the index in the array returned by the nodes property. - * - * @type number - * @name pv.Layout.Network.Node.prototype.index - */ - -/** - * The link degree; the sum of link values for all incoming and outgoing links. - * This attribute is populated automatically. - * - * @type number - * @name pv.Layout.Network.Node.prototype.linkDegree - */ - -/** - * The node name; optional. If present, this attribute will be used to provide - * the text for node labels. If not present, the label text will fallback to the - * nodeValue attribute. - * - * @type string - * @name pv.Layout.Network.Node.prototype.nodeName - */ - -/** - * The node value; optional. If present, and no nodeName attribute is - * present, the node value will be used as the label text. This attribute is - * also automatically populated if the nodes are specified as an array of - * primitives, such as strings or numbers. - * - * @type object - * @name pv.Layout.Network.Node.prototype.nodeValue - */ - -/** - * @class Represents a link in a network layout. There is no explicit - * constructor; this class merely serves to document the attributes that are - * used on links in network layouts. For hierarchical layouts, this class is - * used to represent the parent-child links. - * - * @see pv.Layout.Network - * @name pv.Layout.Network.Link - */ - -/** - * The link value, or weight; optional. If not specified (or not a number), the - * default value of 1 is used. - * - * @type number - * @name pv.Layout.Network.Link.prototype.linkValue - */ - -/** - * The link's source node. If not set, this value will be derived from the - * source attribute index. - * - * @type pv.Layout.Network.Node - * @name pv.Layout.Network.Link.prototype.sourceNode - */ - -/** - * The link's target node. If not set, this value will be derived from the - * target attribute index. - * - * @type pv.Layout.Network.Node - * @name pv.Layout.Network.Link.prototype.targetNode - */ - -/** - * Alias for sourceNode, as expressed by the index of the source node. - * This attribute is not populated automatically, but may be used as a more - * convenient identification of the link's source, for example in a static JSON - * representation. - * - * @type number - * @name pv.Layout.Network.Link.prototype.source - */ - -/** - * Alias for targetNode, as expressed by the index of the target node. - * This attribute is not populated automatically, but may be used as a more - * convenient identification of the link's target, for example in a static JSON - * representation. - * - * @type number - * @name pv.Layout.Network.Link.prototype.target - */ - -/** - * Alias for linkValue. This attribute is not populated automatically, - * but may be used instead of the linkValue attribute when specifying - * links. - * - * @type number - * @name pv.Layout.Network.Link.prototype.value - */ - -/** @private Transform nodes and links on cast. */ -pv.Layout.Network.prototype = pv.extend(pv.Layout) - .property("nodes", function(v) { - return v.map(function(d, i) { - if (typeof d != "object") d = {nodeValue: d}; - d.index = i; - return d; - }); - }) - .property("links", function(v) { - return v.map(function(d) { - if (isNaN(d.linkValue)) d.linkValue = isNaN(d.value) ? 1 : d.value; - return d; - }); - }); - -/** - * Resets the cache, such that changes to layout property definitions will be - * visible on subsequent render. Unlike normal marks (and normal layouts), - * properties associated with network layouts are not automatically re-evaluated - * on render; the properties are cached, and any expensive layout algorithms are - * only run after the layout is explicitly reset. - * - * @returns {pv.Layout.Network} this. - */ -pv.Layout.Network.prototype.reset = function() { - this.$id = pv.id(); - return this; -}; - -/** @private Skip evaluating properties if cached. */ -pv.Layout.Network.prototype.buildProperties = function(s, properties) { - if ((s.$id || 0) < this.$id) { - pv.Layout.prototype.buildProperties.call(this, s, properties); - } -}; - -/** @private Compute link degrees; map source and target indexes to nodes. */ -pv.Layout.Network.prototype.buildImplied = function(s) { - pv.Layout.prototype.buildImplied.call(this, s); - if (s.$id >= this.$id) return true; - s.$id = this.$id; - s.nodes.forEach(function(d) { - d.linkDegree = 0; - }); - s.links.forEach(function(d) { - var v = d.linkValue; - (d.sourceNode || (d.sourceNode = s.nodes[d.source])).linkDegree += v; - (d.targetNode || (d.targetNode = s.nodes[d.target])).linkDegree += v; - }); -}; -/** - * Constructs a new, empty hierarchy layout. Layouts are not typically - * constructed directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Represents an abstract layout for hierarchy diagrams. This class is a - * specialization of {@link pv.Layout.Network}, providing the basic structure - * for both hierarchical node-link diagrams (such as Reingold-Tilford trees) and - * space-filling hierarchy diagrams (such as sunbursts and treemaps). - * - *

Unlike general network layouts, the links property need not be - * defined explicitly. Instead, the links are computed implicitly from the - * parentNode attribute of the node objects, as defined by the - * nodes property. This implementation is also available as - * {@link #links}, for reuse with non-hierarchical layouts; for example, to - * render a tree using force-directed layout. - * - *

Correspondingly, the nodes property is represented as a union of - * {@link pv.Layout.Network.Node} and {@link pv.Dom.Node}. To construct a node - * hierarchy from a simple JSON map, use the {@link pv.Dom} operator; this - * operator also provides an easy way to sort nodes before passing them to the - * layout. - * - *

For more details on how to use this layout, see - * {@link pv.Layout.Network}. - * - * @see pv.Layout.Cluster - * @see pv.Layout.Partition - * @see pv.Layout.Tree - * @see pv.Layout.Treemap - * @see pv.Layout.Indent - * @see pv.Layout.Pack - * @extends pv.Layout.Network - */ -pv.Layout.Hierarchy = function() { - pv.Layout.Network.call(this); - this.link.strokeStyle("#ccc"); -}; - -pv.Layout.Hierarchy.prototype = pv.extend(pv.Layout.Network); - -/** @private Compute the implied links. (Links are null by default.) */ -pv.Layout.Hierarchy.prototype.buildImplied = function(s) { - if (!s.links) s.links = pv.Layout.Hierarchy.links.call(this); - pv.Layout.Network.prototype.buildImplied.call(this, s); -}; - -/** The implied links; computes links using the parentNode attribute. */ -pv.Layout.Hierarchy.links = function() { - return this.nodes() - .filter(function(n) { return n.parentNode; }) - .map(function(n) { - return { - sourceNode: n, - targetNode: n.parentNode, - linkValue: 1 - }; - }); -}; - -/** @private Provides standard node-link layout based on breadth & depth. */ -pv.Layout.Hierarchy.NodeLink = { - - /** @private */ - buildImplied: function(s) { - var nodes = s.nodes, - orient = s.orient, - horizontal = /^(top|bottom)$/.test(orient), - w = s.width, - h = s.height; - - /* Compute default inner and outer radius. */ - if (orient == "radial") { - var ir = s.innerRadius, or = s.outerRadius; - if (ir == null) ir = 0; - if (or == null) or = Math.min(w, h) / 2; - } - - /** @private Returns the radius of the given node. */ - function radius(n) { - return n.parentNode ? (n.depth * (or - ir) + ir) : 0; - } - - /** @private Returns the angle of the given node. */ - function midAngle(n) { - return (n.parentNode ? (n.breadth - .25) * 2 * Math.PI : 0); - } - - /** @private */ - function x(n) { - switch (orient) { - case "left": return n.depth * w; - case "right": return w - n.depth * w; - case "top": return n.breadth * w; - case "bottom": return w - n.breadth * w; - case "radial": return w / 2 + radius(n) * Math.cos(n.midAngle); - } - } - - /** @private */ - function y(n) { - switch (orient) { - case "left": return n.breadth * h; - case "right": return h - n.breadth * h; - case "top": return n.depth * h; - case "bottom": return h - n.depth * h; - case "radial": return h / 2 + radius(n) * Math.sin(n.midAngle); - } - } - - for (var i = 0; i < nodes.length; i++) { - var n = nodes[i]; - n.midAngle = orient == "radial" ? midAngle(n) - : horizontal ? Math.PI / 2 : 0; - n.x = x(n); - n.y = y(n); - if (n.firstChild) n.midAngle += Math.PI; - } - } -}; - -/** @private Provides standard space-filling layout based on breadth & depth. */ -pv.Layout.Hierarchy.Fill = { - - /** @private */ - constructor: function() { - this.node - .strokeStyle("#fff") - .fillStyle("#ccc") - .width(function(n) { return n.dx; }) - .height(function(n) { return n.dy; }) - .innerRadius(function(n) { return n.innerRadius; }) - .outerRadius(function(n) { return n.outerRadius; }) - .startAngle(function(n) { return n.startAngle; }) - .angle(function(n) { return n.angle; }); - - this.label - .textAlign("center") - .left(function(n) { return n.x + (n.dx / 2); }) - .top(function(n) { return n.y + (n.dy / 2); }); - - /* Hide unsupported link. */ - delete this.link; - }, - - /** @private */ - buildImplied: function(s) { - var nodes = s.nodes, - orient = s.orient, - horizontal = /^(top|bottom)$/.test(orient), - w = s.width, - h = s.height, - depth = -nodes[0].minDepth; - - /* Compute default inner and outer radius. */ - if (orient == "radial") { - var ir = s.innerRadius, or = s.outerRadius; - if (ir == null) ir = 0; - if (ir) depth *= 2; // use full depth step for root - if (or == null) or = Math.min(w, h) / 2; - } - - /** @private Scales the specified depth for a space-filling layout. */ - function scale(d, depth) { - return (d + depth) / (1 + depth); - } - - /** @private */ - function x(n) { - switch (orient) { - case "left": return scale(n.minDepth, depth) * w; - case "right": return (1 - scale(n.maxDepth, depth)) * w; - case "top": return n.minBreadth * w; - case "bottom": return (1 - n.maxBreadth) * w; - case "radial": return w / 2; - } - } - - /** @private */ - function y(n) { - switch (orient) { - case "left": return n.minBreadth * h; - case "right": return (1 - n.maxBreadth) * h; - case "top": return scale(n.minDepth, depth) * h; - case "bottom": return (1 - scale(n.maxDepth, depth)) * h; - case "radial": return h / 2; - } - } - - /** @private */ - function dx(n) { - switch (orient) { - case "left": - case "right": return (n.maxDepth - n.minDepth) / (1 + depth) * w; - case "top": - case "bottom": return (n.maxBreadth - n.minBreadth) * w; - case "radial": return n.parentNode ? (n.innerRadius + n.outerRadius) * Math.cos(n.midAngle) : 0; - } - } - - /** @private */ - function dy(n) { - switch (orient) { - case "left": - case "right": return (n.maxBreadth - n.minBreadth) * h; - case "top": - case "bottom": return (n.maxDepth - n.minDepth) / (1 + depth) * h; - case "radial": return n.parentNode ? (n.innerRadius + n.outerRadius) * Math.sin(n.midAngle) : 0; - } - } - - /** @private */ - function innerRadius(n) { - return Math.max(0, scale(n.minDepth, depth / 2)) * (or - ir) + ir; - } - - /** @private */ - function outerRadius(n) { - return scale(n.maxDepth, depth / 2) * (or - ir) + ir; - } - - /** @private */ - function startAngle(n) { - return (n.parentNode ? n.minBreadth - .25 : 0) * 2 * Math.PI; - } - - /** @private */ - function angle(n) { - return (n.parentNode ? n.maxBreadth - n.minBreadth : 1) * 2 * Math.PI; - } - - for (var i = 0; i < nodes.length; i++) { - var n = nodes[i]; - n.x = x(n); - n.y = y(n); - if (orient == "radial") { - n.innerRadius = innerRadius(n); - n.outerRadius = outerRadius(n); - n.startAngle = startAngle(n); - n.angle = angle(n); - n.midAngle = n.startAngle + n.angle / 2; - } else { - n.midAngle = horizontal ? -Math.PI / 2 : 0; - } - n.dx = dx(n); - n.dy = dy(n); - } - } -}; -/** - * Constructs a new, empty grid layout. Layouts are not typically constructed - * directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a grid layout with regularly-sized rows and columns. The - * number of rows and columns are determined from their respective - * properties. For example, the 2×3 array: - * - *

1 2 3
- * 4 5 6
- * - * can be represented using the rows property as: - * - *
[[1, 2, 3], [4, 5, 6]]
- * - * If your data is in column-major order, you can equivalently use the - * columns property. If the rows property is an array, it - * takes priority over the columns property. The data is implicitly - * transposed, as if the {@link pv.transpose} operator were applied. - * - *

This layout exports a single cell mark prototype, which is - * intended to be used with a bar, panel, layout, or subclass thereof. The data - * property of the cell prototype is defined as the elements in the array. For - * example, if the array is a two-dimensional array of values in the range - * [0,1], a simple heatmap can be generated as: - * - *

vis.add(pv.Layout.Grid)
- *     .rows(arrays)
- *   .cell.add(pv.Bar)
- *     .fillStyle(pv.ramp("white", "black"))
- * - * The grid subdivides the full width and height of the parent panel into equal - * rectangles. Note, however, that for large, interactive, or animated heatmaps, - * you may see significantly better performance through dynamic {@link pv.Image} - * generation. - * - *

For irregular grids using value-based spatial partitioning, see {@link - * pv.Layout.Treemap}. - * - * @extends pv.Layout - */ -pv.Layout.Grid = function() { - pv.Layout.call(this); - var that = this; - - /** - * The cell prototype. This prototype is intended to be used with a bar, - * panel, or layout (or subclass thereof) to render the grid cells. - * - * @type pv.Mark - * @name pv.Layout.Grid.prototype.cell - */ - (this.cell = new pv.Mark() - .data(function() { - return that.scene[that.index].$grid; - }) - .width(function() { - return that.width() / that.cols(); - }) - .height(function() { - return that.height() / that.rows(); - }) - .left(function() { - return this.width() * (this.index % that.cols()); - }) - .top(function() { - return this.height() * Math.floor(this.index / that.cols()); - })).parent = this; -}; - -pv.Layout.Grid.prototype = pv.extend(pv.Layout) - .property("rows") - .property("cols"); - -/** - * Default properties for grid layouts. By default, there is one row and one - * column, and the data is the propagated to the child cell. - * - * @type pv.Layout.Grid - */ -pv.Layout.Grid.prototype.defaults = new pv.Layout.Grid() - .extend(pv.Layout.prototype.defaults) - .rows(1) - .cols(1); - -/** @private */ -pv.Layout.Grid.prototype.buildImplied = function(s) { - pv.Layout.prototype.buildImplied.call(this, s); - var r = s.rows, c = s.cols; - if (typeof c == "object") r = pv.transpose(c); - if (typeof r == "object") { - s.$grid = pv.blend(r); - s.rows = r.length; - s.cols = r[0] ? r[0].length : 0; - } else { - s.$grid = pv.repeat([s.data], r * c); - } -}; - -/** - * The number of rows. This property can also be specified as the data in - * row-major order; in this case, the rows property is implicitly set to the - * length of the array, and the cols property is set to the length of the first - * element in the array. - * - * @type number - * @name pv.Layout.Grid.prototype.rows - */ - -/** - * The number of columns. This property can also be specified as the data in - * column-major order; in this case, the cols property is implicitly set to the - * length of the array, and the rows property is set to the length of the first - * element in the array. - * - * @type number - * @name pv.Layout.Grid.prototype.cols - */ -/** - * Constructs a new, empty stack layout. Layouts are not typically constructed - * directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a layout for stacked visualizations, ranging from simple - * stacked bar charts to more elaborate "streamgraphs" composed of stacked - * areas. Stack layouts uses length as a visual encoding, as opposed to - * position, as the layers do not share an aligned axis. - * - *

Marks can be stacked vertically or horizontally. For example, - * - *

vis.add(pv.Layout.Stack)
- *     .layers([[1, 1.2, 1.7, 1.5, 1.7],
- *              [.5, 1, .8, 1.1, 1.3],
- *              [.2, .5, .8, .9, 1]])
- *     .x(function() this.index * 35)
- *     .y(function(d) d * 40)
- *   .layer.add(pv.Area);
- * - * specifies a vertically-stacked area chart, using the default "bottom-left" - * orientation with "zero" offset. This visualization can be easily changed into - * a streamgraph using the "wiggle" offset, which attempts to minimize change in - * slope weighted by layer thickness. See the {@link #offset} property for more - * supported streamgraph algorithms. - * - *

In the simplest case, the layer data can be specified as a two-dimensional - * array of numbers. The x and y psuedo-properties are used to - * define the thickness of each layer at the given position, respectively; in - * the above example of the "bottom-left" orientation, the x and - * y psuedo-properties are equivalent to the left and - * height properties that you might use if you implemented a stacked - * area by hand. - * - *

The advantage of using the stack layout is that the baseline, i.e., the - * bottom property is computed automatically using the specified offset - * algorithm. In addition, the order of layers can be computed using a built-in - * algorithm via the order property. - * - *

With the exception of the "expand" offset, the stack layout does - * not perform any automatic scaling of data; the values returned from - * x and y specify pixel sizes. To simplify scaling math, use - * this layout in conjunction with {@link pv.Scale.linear} or similar. - * - *

In other cases, the values psuedo-property can be used to define - * the data more flexibly. As with a typical panel & area, the - * layers property corresponds to the data in the enclosing panel, - * while the values psuedo-property corresponds to the data for the - * area within the panel. For example, given an array of data values: - * - *

var crimea = [
- *  { date: "4/1854", wounds: 0, other: 110, disease: 110 },
- *  { date: "5/1854", wounds: 0, other: 95, disease: 105 },
- *  { date: "6/1854", wounds: 0, other: 40, disease: 95 },
- *  ...
- * - * and a corresponding array of series names: - * - *
var causes = ["wounds", "other", "disease"];
- * - * Separate layers can be defined for each cause like so: - * - *
vis.add(pv.Layout.Stack)
- *     .layers(causes)
- *     .values(crimea)
- *     .x(function(d) x(d.date))
- *     .y(function(d, p) y(d[p]))
- *   .layer.add(pv.Area)
- *     ...
- * - * As with the panel & area case, the datum that is passed to the - * psuedo-properties x and y are the values (an element in - * crimea); the second argument is the layer data (a string in - * causes). Additional arguments specify the data of enclosing panels, - * if any. - * - * @extends pv.Layout - */ -pv.Layout.Stack = function() { - pv.Layout.call(this); - var that = this, - /** @ignore */ none = function() { return null; }, - prop = {t: none, l: none, r: none, b: none, w: none, h: none}, - values, - buildImplied = that.buildImplied; - - /** @private Proxy the given property on the layer. */ - function proxy(name) { - return function() { - return prop[name](this.parent.index, this.index); - }; - } - - /** @private Compute the layout! */ - this.buildImplied = function(s) { - buildImplied.call(this, s); - - var data = s.layers, - n = data.length, - m, - orient = s.orient, - horizontal = /^(top|bottom)\b/.test(orient), - h = this.parent[horizontal ? "height" : "width"](), - x = [], - y = [], - dy = []; - - /* - * Iterate over the data, evaluating the values, x and y functions. The - * context in which the x and y psuedo-properties are evaluated is a - * pseudo-mark that is a grandchild of this layout. - */ - var stack = pv.Mark.stack, o = {parent: {parent: this}}; - stack.unshift(null); - values = []; - for (var i = 0; i < n; i++) { - dy[i] = []; - y[i] = []; - o.parent.index = i; - stack[0] = data[i]; - values[i] = this.$values.apply(o.parent, stack); - if (!i) m = values[i].length; - stack.unshift(null); - for (var j = 0; j < m; j++) { - stack[0] = values[i][j]; - o.index = j; - if (!i) x[j] = this.$x.apply(o, stack); - dy[i][j] = this.$y.apply(o, stack); - } - stack.shift(); - } - stack.shift(); - - /* order */ - var index; - switch (s.order) { - case "inside-out": { - var max = dy.map(function(v) { return pv.max.index(v); }), - map = pv.range(n).sort(function(a, b) { return max[a] - max[b]; }), - sums = dy.map(function(v) { return pv.sum(v); }), - top = 0, - bottom = 0, - tops = [], - bottoms = []; - for (var i = 0; i < n; i++) { - var j = map[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); - } - } - index = bottoms.reverse().concat(tops); - break; - } - case "reverse": index = pv.range(n - 1, -1, -1); break; - default: index = pv.range(n); break; - } - - /* offset */ - switch (s.offset) { - case "silohouette": { - for (var j = 0; j < m; j++) { - var o = 0; - for (var i = 0; i < n; i++) o += dy[i][j]; - y[index[0]][j] = (h - o) / 2; - } - break; - } - case "wiggle": { - var o = 0; - for (var i = 0; i < n; i++) o += dy[i][0]; - y[index[0]][0] = o = (h - o) / 2; - for (var j = 1; j < m; j++) { - var s1 = 0, s2 = 0, dx = x[j] - x[j - 1]; - for (var i = 0; i < n; i++) s1 += dy[i][j]; - for (var i = 0; i < n; i++) { - var s3 = (dy[index[i]][j] - dy[index[i]][j - 1]) / (2 * dx); - for (var k = 0; k < i; k++) { - s3 += (dy[index[k]][j] - dy[index[k]][j - 1]) / dx; - } - s2 += s3 * dy[index[i]][j]; - } - y[index[0]][j] = o -= s1 ? s2 / s1 * dx : 0; - } - break; - } - case "expand": { - for (var j = 0; j < m; j++) { - y[index[0]][j] = 0; - var k = 0; - for (var i = 0; i < n; i++) k += dy[i][j]; - if (k) { - k = h / k; - for (var i = 0; i < n; i++) dy[i][j] *= k; - } else { - k = h / n; - for (var i = 0; i < n; i++) dy[i][j] = k; - } - } - break; - } - default: { - for (var j = 0; j < m; j++) y[index[0]][j] = 0; - break; - } - } - - /* Propagate the offset to the other series. */ - for (var j = 0; j < m; j++) { - var o = y[index[0]][j]; - for (var i = 1; i < n; i++) { - o += dy[index[i - 1]][j]; - y[index[i]][j] = o; - } - } - - /* Find the property definitions for dynamic substitution. */ - var i = orient.indexOf("-"), - pdy = horizontal ? "h" : "w", - px = i < 0 ? (horizontal ? "l" : "b") : orient.charAt(i + 1), - py = orient.charAt(0); - for (var p in prop) prop[p] = none; - prop[px] = function(i, j) { return x[j]; }; - prop[py] = function(i, j) { return y[i][j]; }; - prop[pdy] = function(i, j) { return dy[i][j]; }; - }; - - /** - * The layer prototype. This prototype is intended to be used with an area, - * bar or panel mark (or subclass thereof). Other mark types may be possible, - * though note that the stack layout is not currently designed to support - * radial stacked visualizations using wedges. - * - *

The layer is not a direct child of the stack layout; a hidden panel is - * used to replicate layers. - * - * @type pv.Mark - * @name pv.Layout.Stack.prototype.layer - */ - this.layer = new pv.Mark() - .data(function() { return values[this.parent.index]; }) - .top(proxy("t")) - .left(proxy("l")) - .right(proxy("r")) - .bottom(proxy("b")) - .width(proxy("w")) - .height(proxy("h")); - - this.layer.add = function(type) { - return that.add(pv.Panel) - .data(function() { return that.layers(); }) - .add(type) - .extend(this); - }; -}; - -pv.Layout.Stack.prototype = pv.extend(pv.Layout) - .property("orient", String) - .property("offset", String) - .property("order", String) - .property("layers"); - -/** - * Default properties for stack layouts. The default orientation is - * "bottom-left", the default offset is "zero", and the default layers is - * [[]]. - * - * @type pv.Layout.Stack - */ -pv.Layout.Stack.prototype.defaults = new pv.Layout.Stack() - .extend(pv.Layout.prototype.defaults) - .orient("bottom-left") - .offset("zero") - .layers([[]]); - -/** @private */ -pv.Layout.Stack.prototype.$x - = /** @private */ pv.Layout.Stack.prototype.$y - = function() { return 0; }; - -/** - * The x psuedo-property; determines the position of the value within the layer. - * This typically corresponds to the independent variable. For example, with the - * default "bottom-left" orientation, this function defines the "left" property. - * - * @param {function} f the x function. - * @returns {pv.Layout.Stack} this. - */ -pv.Layout.Stack.prototype.x = function(f) { - /** @private */ this.$x = pv.functor(f); - return this; -}; - -/** - * The y psuedo-property; determines the thickness of the layer at the given - * value. This typically corresponds to the dependent variable. For example, - * with the default "bottom-left" orientation, this function defines the - * "height" property. - * - * @param {function} f the y function. - * @returns {pv.Layout.Stack} this. - */ -pv.Layout.Stack.prototype.y = function(f) { - /** @private */ this.$y = pv.functor(f); - return this; -}; - -/** @private The default value function; identity. */ -pv.Layout.Stack.prototype.$values = pv.identity; - -/** - * The values function; determines the values for a given layer. The default - * value is the identity function, which assumes that the layers property is - * specified as a two-dimensional (i.e., nested) array. - * - * @param {function} f the values function. - * @returns {pv.Layout.Stack} this. - */ -pv.Layout.Stack.prototype.values = function(f) { - this.$values = pv.functor(f); - return this; -}; - -/** - * The layer data in row-major order. The value of this property is typically a - * two-dimensional (i.e., nested) array, but any array can be used, provided the - * values psuedo-property is defined accordingly. - * - * @type array[] - * @name pv.Layout.Stack.prototype.layers - */ - -/** - * The layer orientation. The following values are supported:

    - * - *
  • bottom-left == bottom - *
  • bottom-right - *
  • top-left == top - *
  • top-right - *
  • left-top - *
  • left-bottom == left - *
  • right-top - *
  • right-bottom == right - * - *
. The default value is "bottom-left", which means that the layers will - * be built from the bottom-up, and the values within layers will be laid out - * from left-to-right. - * - *

Note that with non-zero baselines, some orientations may give similar - * results. For example, offset("silohouette") centers the layers, resulting in - * a streamgraph. Thus, the orientations "bottom-left" and "top-left" will - * produce similar results, differing only in the layer order. - * - * @type string - * @name pv.Layout.Stack.prototype.orient - */ - -/** - * The layer order. The following values are supported:

    - * - *
  • null - use given layer order. - *
  • inside-out - sort by maximum value, with balanced order. - *
  • reverse - use reverse of given layer order. - * - *
For details on the inside-out order algorithm, refer to "Stacked Graphs - * -- Geometry & Aesthetics" by L. Byron and M. Wattenberg, IEEE TVCG - * November/December 2008. - * - * @type string - * @name pv.Layout.Stack.prototype.order - */ - -/** - * The layer offset; the y-position of the bottom of the lowest layer. The - * following values are supported:
    - * - *
  • zero - use a zero baseline, i.e., the y-axis. - *
  • silohouette - center the stream, i.e., ThemeRiver. - *
  • wiggle - minimize weighted change in slope. - *
  • expand - expand layers to fill the enclosing layout dimensions. - * - *
For details on these offset algorithms, refer to "Stacked Graphs -- - * Geometry & Aesthetics" by L. Byron and M. Wattenberg, IEEE TVCG - * November/December 2008. - * - * @type string - * @name pv.Layout.Stack.prototype.offset - */ -/** - * Constructs a new, empty band layout. Layouts are not typically constructed - * directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a layout for banded visualizations; it is - * mainly used for grouped bar charts. - * - * @extends pv.Layout - */ -pv.Layout.Band = function() { - - pv.Layout.call(this); - - var that = this, - buildImplied = that.buildImplied, - itemProps, - values; - - /** - * The prototype mark of the items mark. - */ - var itemProto = new pv.Mark() - .data (function(){return values[this.parent.index];}) - .top (proxy("t")) - .left (proxy("l")) - .right (proxy("r")) - .bottom(proxy("b")) - .width (proxy("w")) - .height(proxy("h")); - - /** - * Proxy the given property for an item of a band. - * @private - */ - function proxy(name) { - return function() { - /* bandIndex, layerIndex */ - return itemProps[name](this.index, this.parent.index); - }; - } - - /** - * Compute the layout. - * @private - */ - this.buildImplied = function(s) { - buildImplied.call(this, s); - - /* Update shared fields */ - itemProps = Object.create(pv.Layout.Band.$baseItemProps); - values = []; - - var data = s.layers, - L = data.length; - if(L > 0){ - var orient = s.orient, - horizontal = /^(top|bottom)\b/.test(orient), - bh = this.parent[horizontal ? "height" : "width"](), - bands = this._readData(data, values, s), - B = bands.length; - - /* Band order */ - if(s.bandOrder === "reverse") { - bands.reverse(); - } - - /* Layer order */ - if(s.order === "reverse") { - values.reverse(); - - for (var b = 0; b < B; b++) { - bands[b].items.reverse(); - } - } - - /* Layout kind */ - switch(s.layout){ - case "grouped": this._calcGrouped(bands, L, s); break; - case "stacked": this._calcStacked(bands, L, bh, s); break; - } - - this._bindItemProps(bands, itemProps, orient, horizontal); - } - }; - - var itemAccessor = this.item = { - end: this, - - add: function(type) { - return that.add(pv.Panel) - .data(function(){return that.layers();}) - .add(type) - .extend(itemProto); - }, - - order: function(value){ - that.order(value); - return this; - }, - - /** - * The item width pseudo-property; - * determines the width of an item. - */ - w: function(f){ - that.$iw = pv.functor(f); - return this; - }, - - /** - * The item height pseudo-property; - * determines the height of an item. - */ - h: function(f){ - that.$ih = pv.functor(f); - return this; - }, - - /** - * The percentage of total item width to band width - * in a grouped layout. - *

- * The empty space is equally distributed in - * separating items within a band. - *

- *

- * Evaluated once per band - * (on the corresponding band's item of the first series). - *

- *
-				 * f: (item, series) -> percentage
-				 * 
- */ - horizontalRatio: function(f){ - that.$ihorizRatio = pv.functor(f); - return this; - }, - - /** - * The vertical margin that separates stacked items, - * in a stacked layout. - *

- * Half the specified margin is discounted - * from each of the items own height. - *

- * - *

- * Evaluated once per band - * (on the corresponding band's item of the first series). - *

- *
-				 * f: (item, series) -> height
-				 * 
- */ - verticalMargin: function(f){ - that.$ivertiMargin = pv.functor(f); - return this; - } - }; - - var bandAccessor = this.band = { - end: this, - - /** - * The band width pseudo-property; - * determines the width of a band - * when the item layout grouped. - *

- * Evaluated once per band - * (on the corresponding band's item of the first series). - *

- *
-				 * f: (item, series) -> width
-				 * 
- */ - w: function(f){ - that.$bw = pv.functor(f); - return this; - }, - - /** - * The band x pseudo-property; - * determines the x center position of a band - * in a layer panel. - * - *

- * Evaluated once per band - * (on the corresponding band's item of the first series). - *

- *
-				 * f: (item, series) -> x
-				 * 
- */ - x: function(f){ - that.$bx = pv.functor(f); - return this; - }, - - order: function(value){ - that.bandOrder(value); - return this; - }, - - /** - * Band differential control pseudo-property. - * 2 - Drawn starting at previous band offset. Multiply values by 1. Don't update offset. - * 1 - Drawn starting at previous band offset. Multiply values by 1. Update offset. - * 0 - Reset offset to 0. Drawn starting at 0. Default. Leave offset at 0. - * -1 - Drawn starting at previous band offset. Multiply values by -1. Update offset. - * -2 - Drawn starting at previous band offset. Multiply values by -1. Don't update offset. - * @private - */ - differentialControl: function(f){ - that.$bDiffControl = pv.functor(f); - return this; - } - }; - - this.band.item = itemAccessor; - this.item.band = bandAccessor; -}; - -pv.Layout.Band.$baseItemProps = (function(){ - var none = function() {return null;}; - return {t: none, l: none, r: none, b: none, w: none, h: none}; -}()); - -pv.Layout.Band.prototype = pv.extend(pv.Layout) - .property("orient", String) // x-y orientation - .property("layout", String) // items layout within band: "grouped", "stacked" - .property("layers") // data - .property("yZero", Number) // The y zero base line - .property("verticalMode", String) // The vertical mode: 'expand', null - .property("horizontalMode", String) // The horizontal mode: 'expand', null - .property("order", String) // layer order; "reverse" or null - .property("bandOrder", String) // band order; "reverse" or null - ; - -/** - * Default properties for stack layouts. - * The default orientation is "bottom-left", - * the default layout is "grouped", - * the default y zero base line is 0, and - * the default layers is [[]]. - * - * @type pv.Layout.Band - */ -pv.Layout.Band.prototype.defaults = new pv.Layout.Band() - .extend(pv.Layout.prototype.defaults) - .orient("bottom-left") - .layout("grouped") - .yZero(0) - .layers([[]]) - ; - -/** @private */ pv.Layout.Band.prototype.$bx = -/** @private */ pv.Layout.Band.prototype.$bw = -/** @private */ pv.Layout.Band.prototype.$bDiffControl = -/** @private */ pv.Layout.Band.prototype.$iw = -/** @private */ pv.Layout.Band.prototype.$ih = -/** @private */ pv.Layout.Band.prototype.$ivertiMargin = pv.functor(0); - -/** @private */ pv.Layout.Band.prototype.$ihorizRatio = pv.functor(0.9); - -/** @private The default values function; identity. */ -pv.Layout.Band.prototype.$values = pv.identity; - -/** - * The values function; determines the values for a given band. - * The default value is the identity function, - * which assumes that the bands property is specified as - * a two-dimensional (i.e., nested) array. - * - * @param {function} f the values function. - * @returns {pv.Layout.Band} this. - */ -pv.Layout.Band.prototype.values = function(f) { - this.$values = pv.functor(f); - return this; -}; - -pv.Layout.prototype._readData = function(data, layersValues, scene){ - var L = data.length, - bands = [ - /* - { - x: 0, // x left position of each band - w: 0, // width of each band - iwr: 0, // item width ratio of each band - items: [ // indexed by series index - { - h: 0, // height of each item - w: 0, // width of each item - x: 0 // position of each item (within its band) (calculated) - } - ] - } - */ - ], - B; - - /* - * Iterate over the data, evaluating the values, x and y functions. - * The context in which the x and y pseudo-properties are evaluated is a - * pseudo-mark that is a *grandchild* of this layout. - */ - var stack = pv.Mark.stack, - o = {parent: {parent: this}}; - - stack.unshift(null); - - for (var l = 0; l < L; l++) { - o.parent.index = l; - stack[0] = data[l]; - - /* Eval per-layer properties */ - - var layerValues = layersValues[l] = this.$values.apply(o.parent, stack); - if(!l){ - B = layerValues.length; - } - - /* Eval per-item properties */ - stack.unshift(null); - for (var b = 0; b < B ; b++) { - stack[0] = layerValues[b]; - o.index = b; - - /* First series evaluates band stuff, for each band */ - var band = bands[b]; - if(!band){ - band = bands[b] = { - horizRatio: this.$ihorizRatio.apply(o, stack), - vertiMargin: this.$ivertiMargin.apply(o, stack), - w: this.$bw.apply(o, stack), - x: this.$bx.apply(o, stack), - diffControl: this.$bDiffControl ? this.$bDiffControl.apply(o, stack) : 0, - items: [] - }; - } - - var ih = this.$ih.apply(o, stack); // may be null - band.items[l] = { - y: (scene.yZero || 0), - x: 0, - w: this.$iw.apply(o, stack), - h: ih != null ? Math.abs(ih) : ih, - dir: ih < 0 ? -1 : 1 // null -> 1 - }; - } - stack.shift(); - } - stack.shift(); - - return bands; -}; - -pv.Layout.Band.prototype._calcGrouped = function(bands, L, scene){ - /* Compute item x positions relative to parent panel */ - for (var b = 0, B = bands.length; b < B ; b++) { - var band = bands[b], - items = band.items, - w = band.w, - horizRatio = band.horizRatio, - wItems = 0; - - /* Total items width */ - for (var l = 0 ; l < L ; l++) { - wItems += items[l].w; - } - - if(L === 1){ - /* - * Horizontal ratio does not apply - * There's no space between... - */ - horizRatio = 1; - } else if(!(horizRatio > 0 && horizRatio <= 1)) { - horizRatio = 1; - } - - if(w == null){ - /* Expand band width to contain all items plus ratio */ - w = band.w = wItems / horizRatio; - - } else if(scene.horizontalMode === 'expand'){ - /* Scale items width to fit in band's width */ - - var wItems2 = horizRatio * w; - if (wItems) { - var wScale = wItems2 / wItems; - for (var l = 0 ; l < L ; l++) { - items[l].w *= wScale; - } - } else { - var wiavg = wItems2 / L; - for (var l = 0 ; l < L; l++) { - items[l].w = wiavg; - } - } - - wItems = wItems2; - } - - var wItemsWithMargin = wItems / horizRatio, - /* items start x position */ - ix = band.x - (wItemsWithMargin / 2), - margin = L > 1 ? ((wItemsWithMargin - wItems) / (L - 1)) : 0; - - for (var l = 0 ; l < L ; l++) { - var item = items[l]; - item.x = ix; - ix += item.w + margin; - - /* Negative direction turns into a lower iy */ - if(item.dir < 0){ - item.y -= item.h; - } - } - } -}; - -pv.Layout.Band.prototype._calcStacked = function(bands, L, bh, scene){ - var B = bands.length, - items; - - if(scene.verticalMode === "expand") { - for (var b = 0; b < B; b++) { - items = bands[b].items; - - /* Sum across layers for this band */ - var hSum = null, nonNullCount = 0; - for (var l = 0; l < L; l++) { - /* We get rid of negative heights - * because it is preferable to respect the layer's order - * in this case, than to group negative and positive layers, - * taking them out of order. - */ - var item = items[l]; - item.dir = 1; - var h = item.h; - if(h != null){ - nonNullCount++; - hSum += h; // null + 1 = 0 + 1 - } - } - - /* Scale hs */ - if(nonNullCount){ - if (hSum) { - var hScale = bh / hSum; - for (var l = 0; l < L; l++) { - var h = items[l].h; - if(h != null){ - items[l].h = h * hScale; - } - } - } else { - var hAvg = bh / nonNullCount; - for (var l = 0; l < L; l++) { - var h = items[l].h; - if(h != null){ - items[l].h = hAvg; - } - } - } - } - } - } - - /* - * Propagate y offset to other layers. - * Assign width. - * Calc x position. - * Discount vertiMargin - */ - var yZero = scene.yZero, - yOffset = yZero; - - for (var b = 0; b < B; b++) { - var band = bands[b], - bx = band.x, // centered on band - bDiffControl = band.diffControl, - invertDir = (bDiffControl < 0), // -1 or -2 - vertiMargin = band.vertiMargin > 0 ? band.vertiMargin : 0; - - items = band.items; - - // diffControl - var resultPos = this._layoutItemsOfDir(+1, invertDir, items, vertiMargin, bx, yOffset), - resultNeg; - if(resultPos.existsOtherDir){ - resultNeg = this._layoutItemsOfDir(-1, invertDir, items, vertiMargin, bx, yOffset); - } - - if(bDiffControl){ - if(Math.abs(bDiffControl) === 1){ - var yOffset0 = yOffset; - yOffset = resultPos.yOffset; - if(resultNeg){ - yOffset -= (yOffset0 - resultNeg.yOffset); - } - } // otherwise leave offset untouched - } else { // ensure zero - yOffset = yZero; - } - } -}; - -pv.Layout.Band.prototype._layoutItemsOfDir = function(stackDir, invertDir, items, vertiMargin, bx, yOffset){ - var existsOtherDir = false, - vertiMargin2 = vertiMargin / 2, - efDir = (invertDir ? -stackDir : stackDir), - reverseLayers = invertDir; - - for (var l = 0, L = items.length ; l < L ; l+=1) { - var item = items[reverseLayers ? (L -l -1) : l]; - if(item.dir === stackDir){ - var h = item.h || 0; // null -> 0 - - if(efDir > 0){ - item.y = yOffset + vertiMargin2; - yOffset += h; - } else { - item.y = yOffset - (h - vertiMargin2); - yOffset -= h; - } - - var h2 = item.h - vertiMargin; - item.h = h2 > 0 ? h2 : 0; - item.x = bx - item.w / 2; - } else { - existsOtherDir = true; - } - } - - return { - existsOtherDir: existsOtherDir, - yOffset: yOffset - }; -}; - -pv.Layout.Band.prototype._bindItemProps = function(bands, itemProps, orient, horizontal){ - /* - * Find the property definitions for dynamic substitution. - * - * orient = xOrientation-yOrientation - */ - var index = orient.indexOf("-"), - ph = horizontal ? "h" : "w", - pw = horizontal ? "w" : "h", - px = index < 0 ? - /* Default yOrientation - * horizontal -> left - * vertical -> bottom - */ - (horizontal ? "l" : "b") : - /* - * -l,r,t,b ... - */ - orient.charAt(index + 1), - - /* - * b,t,l,r - */ - py = orient.charAt(0); - - itemProps[px] = function(b, l) {return bands[b].items[l].x;}; - itemProps[py] = function(b, l) {return bands[b].items[l].y;}; - itemProps[pw] = function(b, l) {return bands[b].items[l].w;}; - itemProps[ph] = function(b, l) {return bands[b].items[l].h || 0;}; // null -> 0 -}; -/** - * Constructs a new, empty treemap layout. Layouts are not typically - * constructed directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a space-filling rectangular layout, with the hierarchy - * represented via containment. Treemaps represent nodes as boxes, with child - * nodes placed within parent boxes. The size of each box is proportional to the - * size of the node in the tree. This particular algorithm is taken from Bruls, - * D.M., C. Huizing, and J.J. van Wijk, "Squarified Treemaps" in - * Data Visualization 2000, Proceedings of the Joint Eurographics and IEEE - * TCVG Sumposium on Visualization, 2000, pp. 33-42. - * - *

The meaning of the exported mark prototypes changes slightly in the - * space-filling implementation:

    - * - *
  • node - for rendering nodes; typically a {@link pv.Bar}. The node - * data is populated with dx and dy attributes, in addition to - * the standard x and y position attributes. - * - *

  • leaf - for rendering leaf nodes only, with no fill or stroke - * style by default; typically a {@link pv.Panel} or another layout! - * - *

  • link - unsupported; undefined. Links are encoded implicitly - * in the arrangement of the space-filling nodes. - * - *

  • label - for rendering node labels; typically a - * {@link pv.Label}. - * - *
For more details on how to use this layout, see - * {@link pv.Layout.Hierarchy}. - * - * @extends pv.Layout.Hierarchy - */ -pv.Layout.Treemap = function() { - pv.Layout.Hierarchy.call(this); - - this.node - .strokeStyle("#fff") - .fillStyle("rgba(31, 119, 180, .25)") - .width(function(n) { return n.dx; }) - .height(function(n) { return n.dy; }); - - this.label - .visible(function(n) { return !n.firstChild; }) - .left(function(n) { return n.x + (n.dx / 2); }) - .top(function(n) { return n.y + (n.dy / 2); }) - .textAlign("center") - .textAngle(function(n) { return n.dx > n.dy ? 0 : -Math.PI / 2; }); - - (this.leaf = new pv.Mark() - .extend(this.node) - .fillStyle(null) - .strokeStyle(null) - .visible(function(n) { return !n.firstChild; })).parent = this; - - /* Hide unsupported link. */ - delete this.link; -}; - -pv.Layout.Treemap.prototype = pv.extend(pv.Layout.Hierarchy) - .property("round", Boolean) - .property("paddingLeft", Number) - .property("paddingRight", Number) - .property("paddingTop", Number) - .property("paddingBottom", Number) - .property("mode", String) - .property("order", String); - -/** - * Default propertiess for treemap layouts. The default mode is "squarify" and - * the default order is "ascending". - * - * @type pv.Layout.Treemap - */ -pv.Layout.Treemap.prototype.defaults = new pv.Layout.Treemap() - .extend(pv.Layout.Hierarchy.prototype.defaults) - .mode("squarify") // squarify, slice-and-dice, slice, dice - .order("ascending"); // ascending, descending, reverse, null - -/** - * Whether node sizes should be rounded to integer values. This has a similar - * effect to setting antialias(false) for node values, but allows the - * treemap algorithm to accumulate error related to pixel rounding. - * - * @type boolean - * @name pv.Layout.Treemap.prototype.round - */ - -/** - * The left inset between parent add child in pixels. Defaults to 0. - * - * @type number - * @name pv.Layout.Treemap.prototype.paddingLeft - * @see #padding - */ - -/** - * The right inset between parent add child in pixels. Defaults to 0. - * - * @type number - * @name pv.Layout.Treemap.prototype.paddingRight - * @see #padding - */ - -/** - * The top inset between parent and child in pixels. Defaults to 0. - * - * @type number - * @name pv.Layout.Treemap.prototype.paddingTop - * @see #padding - */ - -/** - * The bottom inset between parent and child in pixels. Defaults to 0. - * - * @type number - * @name pv.Layout.Treemap.prototype.paddingBottom - * @see #padding - */ - -/** - * The treemap algorithm. The default value is "squarify". The "slice-and-dice" - * algorithm may also be used, which alternates between horizontal and vertical - * slices for different depths. In addition, the "slice" and "dice" algorithms - * may be specified explicitly to control whether horizontal or vertical slices - * are used, which may be useful for nested treemap layouts. - * - * @type string - * @name pv.Layout.Treemap.prototype.mode - * @see "Ordered Treemap Layouts" by B. Shneiderman & M. Wattenberg, IEEE - * InfoVis 2001. - */ - -/** - * The sibling node order. A null value means to use the sibling order - * specified by the nodes property as-is; "reverse" will reverse the given - * order. The default value "ascending" will sort siblings in ascending order of - * size, while "descending" will do the reverse. For sorting based on data - * attributes other than size, use the default null for the order - * property, and sort the nodes beforehand using the {@link pv.Dom} operator. - * - * @type string - * @name pv.Layout.Treemap.prototype.order - */ - -/** - * Alias for setting the left, right, top and bottom padding properties - * simultaneously. - * - * @see #paddingLeft - * @see #paddingRight - * @see #paddingTop - * @see #paddingBottom - * @returns {pv.Layout.Treemap} this. - */ -pv.Layout.Treemap.prototype.padding = function(n) { - return this.paddingLeft(n).paddingRight(n).paddingTop(n).paddingBottom(n); -}; - -/** @private The default size function. */ -pv.Layout.Treemap.prototype.$size = function(d) { - return Number(d.nodeValue); -}; - -/** - * Specifies the sizing function. By default, the size function uses the - * nodeValue attribute of nodes as a numeric value: function(d) - * Number(d.nodeValue). - * - *

The sizing function is invoked for each leaf node in the tree, per the - * nodes property. For example, if the tree data structure represents a - * file system, with files as leaf nodes, and each file has a bytes - * attribute, you can specify a size function as: - * - *

    .size(function(d) d.bytes)
- * - * @param {function} f the new sizing function. - * @returns {pv.Layout.Treemap} this. - */ -pv.Layout.Treemap.prototype.size = function(f) { - this.$size = pv.functor(f); - return this; -}; - -/** @private */ -pv.Layout.Treemap.prototype.buildImplied = function(s) { - if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return; - - var that = this, - nodes = s.nodes, - root = nodes[0], - stack = pv.Mark.stack, - left = s.paddingLeft, - right = s.paddingRight, - top = s.paddingTop, - bottom = s.paddingBottom, - /** @ignore */ size = function(n) { return n.size; }, - round = s.round ? Math.round : Number, - mode = s.mode; - - /** @private */ - function slice(row, sum, horizontal, x, y, w, h) { - for (var i = 0, d = 0; i < row.length; i++) { - var n = row[i]; - if (horizontal) { - n.x = x + d; - n.y = y; - d += n.dx = round(w * n.size / sum); - n.dy = h; - } else { - n.x = x; - n.y = y + d; - n.dx = w; - d += n.dy = round(h * n.size / sum); - } - } - if (n) { // correct on-axis rounding error - if (horizontal) { - n.dx += w - d; - } else { - n.dy += h - d; - } - } - } - - /** @private */ - function ratio(row, l) { - var rmax = -Infinity, rmin = Infinity, s = 0; - for (var i = 0; i < row.length; i++) { - var r = row[i].size; - if (r < rmin) rmin = r; - if (r > rmax) rmax = r; - s += r; - } - s = s * s; - l = l * l; - return Math.max(l * rmax / s, s / (l * rmin)); - } - - /** @private */ - function layout(n, i) { - var x = n.x + left, - y = n.y + top, - w = n.dx - left - right, - h = n.dy - top - bottom; - - /* Assume squarify by default. */ - if (mode != "squarify") { - slice(n.childNodes, n.size, - mode == "slice" ? true - : mode == "dice" ? false - : i & 1, x, y, w, h); - return; - } - - var row = [], - mink = Infinity, - l = Math.min(w, h), - k = w * h / n.size; - - /* Abort if the size is nonpositive. */ - if (n.size <= 0) return; - - /* Scale the sizes to fill the current subregion. */ - n.visitBefore(function(n) { n.size *= k; }); - - /** @private Position the specified nodes along one dimension. */ - function position(row) { - var horizontal = w == l, - sum = pv.sum(row, size), - r = l ? round(sum / l) : 0; - slice(row, sum, horizontal, x, y, horizontal ? w : r, horizontal ? r : h); - if (horizontal) { - y += r; - h -= r; - } else { - x += r; - w -= r; - } - l = Math.min(w, h); - return horizontal; - } - - var children = n.childNodes.slice(); // copy - while (children.length) { - var child = children[children.length - 1]; - if (!child.size) { - children.pop(); - continue; - } - row.push(child); - - var k = ratio(row, l); - if (k <= mink) { - children.pop(); - mink = k; - } else { - row.pop(); - position(row); - row.length = 0; - mink = Infinity; - } - } - - /* correct off-axis rounding error */ - if (position(row)) for (var i = 0; i < row.length; i++) { - row[i].dy += h; - } else for (var i = 0; i < row.length; i++) { - row[i].dx += w; - } - } - - /* Recursively compute the node depth and size. */ - stack.unshift(null); - root.visitAfter(function(n, i) { - n.depth = i; - n.x = n.y = n.dx = n.dy = 0; - n.size = n.firstChild - ? pv.sum(n.childNodes, function(n) { return n.size; }) - : that.$size.apply(that, (stack[0] = n, stack)); - }); - stack.shift(); - - /* Sort. */ - switch (s.order) { - case "ascending": { - root.sort(function(a, b) { return a.size - b.size; }); - break; - } - case "descending": { - root.sort(function(a, b) { return b.size - a.size; }); - break; - } - case "reverse": root.reverse(); break; - } - - /* Recursively compute the layout. */ - root.x = 0; - root.y = 0; - root.dx = s.width; - root.dy = s.height; - root.visitBefore(layout); -}; -/** - * Constructs a new, empty tree layout. Layouts are not typically constructed - * directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a node-link tree diagram using the Reingold-Tilford "tidy" - * tree layout algorithm. The specific algorithm used by this layout is based on - * "Improving - * Walker's Algorithm to Run in Linear Time" by C. Buchheim, M. Jünger - * & S. Leipert, Graph Drawing 2002. This layout supports both cartesian and - * radial orientations orientations for node-link diagrams. - * - *

The tree layout supports a "group" property, which if true causes siblings - * to be positioned closer together than unrelated nodes at the same depth. The - * layout can be configured using the depth and breadth - * properties, which control the increments in pixel space between nodes in both - * dimensions, similar to the indent layout. - * - *

For more details on how to use this layout, see - * {@link pv.Layout.Hierarchy}. - * - * @extends pv.Layout.Hierarchy - */ -pv.Layout.Tree = function() { - pv.Layout.Hierarchy.call(this); -}; - -pv.Layout.Tree.prototype = pv.extend(pv.Layout.Hierarchy) - .property("group", Number) - .property("breadth", Number) - .property("depth", Number) - .property("orient", String); - -/** - * Default properties for tree layouts. The default orientation is "top", the - * default group parameter is 1, and the default breadth and depth offsets are - * 15 and 60 respectively. - * - * @type pv.Layout.Tree - */ -pv.Layout.Tree.prototype.defaults = new pv.Layout.Tree() - .extend(pv.Layout.Hierarchy.prototype.defaults) - .group(1) - .breadth(15) - .depth(60) - .orient("top"); - -/** @private */ -pv.Layout.Tree.prototype.buildImplied = function(s) { - if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return; - - var nodes = s.nodes, - orient = s.orient, - depth = s.depth, - breadth = s.breadth, - group = s.group, - w = s.width, - h = s.height; - - /** @private */ - function firstWalk(v) { - var l, r, a; - if (!v.firstChild) { - if (l = v.previousSibling) { - v.prelim = l.prelim + distance(v.depth, true); - } - } else { - l = v.firstChild; - r = v.lastChild; - a = l; // default ancestor - for (var c = l; c; c = c.nextSibling) { - firstWalk(c); - a = apportion(c, a); - } - executeShifts(v); - var midpoint = .5 * (l.prelim + r.prelim); - if (l = v.previousSibling) { - v.prelim = l.prelim + distance(v.depth, true); - v.mod = v.prelim - midpoint; - } else { - v.prelim = midpoint; - } - } - } - - /** @private */ - function secondWalk(v, m, depth) { - v.breadth = v.prelim + m; - m += v.mod; - for (var c = v.firstChild; c; c = c.nextSibling) { - secondWalk(c, m, depth); - } - } - - /** @private */ - function apportion(v, a) { - var w = v.previousSibling; - if (w) { - var vip = v, - vop = v, - vim = w, - vom = v.parentNode.firstChild, - sip = vip.mod, - sop = vop.mod, - sim = vim.mod, - som = vom.mod, - nr = nextRight(vim), - nl = nextLeft(vip); - while (nr && nl) { - vim = nr; - vip = nl; - vom = nextLeft(vom); - vop = nextRight(vop); - vop.ancestor = v; - var shift = (vim.prelim + sim) - (vip.prelim + sip) + distance(vim.depth, false); - if (shift > 0) { - moveSubtree(ancestor(vim, v, a), v, shift); - sip += shift; - sop += shift; - } - sim += vim.mod; - sip += vip.mod; - som += vom.mod; - sop += vop.mod; - nr = nextRight(vim); - nl = nextLeft(vip); - } - if (nr && !nextRight(vop)) { - vop.thread = nr; - vop.mod += sim - sop; - } - if (nl && !nextLeft(vom)) { - vom.thread = nl; - vom.mod += sip - som; - a = v; - } - } - return a; - } - - /** @private */ - function nextLeft(v) { - return v.firstChild || v.thread; - } - - /** @private */ - function nextRight(v) { - return v.lastChild || v.thread; - } - - /** @private */ - function moveSubtree(wm, wp, shift) { - var subtrees = wp.number - wm.number; - wp.change -= shift / subtrees; - wp.shift += shift; - wm.change += shift / subtrees; - wp.prelim += shift; - wp.mod += shift; - } - - /** @private */ - function executeShifts(v) { - var shift = 0, change = 0; - for (var c = v.lastChild; c; c = c.previousSibling) { - c.prelim += shift; - c.mod += shift; - change += c.change; - shift += c.shift + change; - } - } - - /** @private */ - function ancestor(vim, v, a) { - return (vim.ancestor.parentNode == v.parentNode) ? vim.ancestor : a; - } - - /** @private */ - function distance(depth, siblings) { - return (siblings ? 1 : (group + 1)) / ((orient == "radial") ? depth : 1); - } - - /* Initialize temporary layout variables. TODO: store separately. */ - var root = nodes[0]; - root.visitAfter(function(v, i) { - v.ancestor = v; - v.prelim = 0; - v.mod = 0; - v.change = 0; - v.shift = 0; - v.number = v.previousSibling ? (v.previousSibling.number + 1) : 0; - v.depth = i; - }); - - /* Compute the layout using Buchheim et al.'s algorithm. */ - firstWalk(root); - secondWalk(root, -root.prelim, 0); - - /** @private Returns the angle of the given node. */ - function midAngle(n) { - return (orient == "radial") ? n.breadth / depth : 0; - } - - /** @private */ - function x(n) { - switch (orient) { - case "left": return n.depth; - case "right": return w - n.depth; - case "top": - case "bottom": return n.breadth + w / 2; - case "radial": return w / 2 + n.depth * Math.cos(midAngle(n)); - } - } - - /** @private */ - function y(n) { - switch (orient) { - case "left": - case "right": return n.breadth + h / 2; - case "top": return n.depth; - case "bottom": return h - n.depth; - case "radial": return h / 2 + n.depth * Math.sin(midAngle(n)); - } - } - - /* Clear temporary layout variables; transform depth and breadth. */ - root.visitAfter(function(v) { - v.breadth *= breadth; - v.depth *= depth; - v.midAngle = midAngle(v); - v.x = x(v); - v.y = y(v); - if (v.firstChild) v.midAngle += Math.PI; - delete v.breadth; - delete v.depth; - delete v.ancestor; - delete v.prelim; - delete v.mod; - delete v.change; - delete v.shift; - delete v.number; - delete v.thread; - }); -}; - -/** - * The offset between siblings nodes; defaults to 15. - * - * @type number - * @name pv.Layout.Tree.prototype.breadth - */ - -/** - * The offset between parent and child nodes; defaults to 60. - * - * @type number - * @name pv.Layout.Tree.prototype.depth - */ - -/** - * The orientation. The default orientation is "top", which means that the root - * node is placed on the top edge, leaf nodes appear at the bottom, and internal - * nodes are in-between. The following orientations are supported:

    - * - *
  • left - left-to-right. - *
  • right - right-to-left. - *
  • top - top-to-bottom. - *
  • bottom - bottom-to-top. - *
  • radial - radially, with the root at the center.
- * - * @type string - * @name pv.Layout.Tree.prototype.orient - */ - -/** - * The sibling grouping, i.e., whether differentiating space is placed between - * sibling groups. The default is 1 (or true), causing sibling leaves to be - * separated by one breadth offset. Setting this to false (or 0) causes - * non-siblings to be adjacent. - * - * @type number - * @name pv.Layout.Tree.prototype.group - */ -/** - * Constructs a new, empty indent layout. Layouts are not typically constructed - * directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a hierarchical layout using the indent algorithm. This - * layout implements a node-link diagram where the nodes are presented in - * preorder traversal, and nodes are indented based on their depth from the - * root. This technique is used ubiquitously by operating systems to represent - * file directories; although it requires much vertical space, indented trees - * allow efficient interactive exploration of trees to find a specific - * node. In addition they allow rapid scanning of node labels, and multivariate - * data such as file sizes can be displayed adjacent to the hierarchy. - * - *

The indent layout can be configured using the depth and - * breadth properties, which control the increments in pixel space for - * each indent and row in the layout. This layout does not support multiple - * orientations; the root node is rendered in the top-left, while - * breadth is a vertical offset from the top, and depth is a - * horizontal offset from the left. - * - *

For more details on how to use this layout, see - * {@link pv.Layout.Hierarchy}. - * - * @extends pv.Layout.Hierarchy - */ -pv.Layout.Indent = function() { - pv.Layout.Hierarchy.call(this); - this.link.interpolate("step-after"); -}; - -pv.Layout.Indent.prototype = pv.extend(pv.Layout.Hierarchy) - .property("depth", Number) - .property("breadth", Number); - -/** - * The horizontal offset between different levels of the tree; defaults to 15. - * - * @type number - * @name pv.Layout.Indent.prototype.depth - */ - -/** - * The vertical offset between nodes; defaults to 15. - * - * @type number - * @name pv.Layout.Indent.prototype.breadth - */ - -/** - * Default properties for indent layouts. By default the depth and breadth - * offsets are 15 pixels. - * - * @type pv.Layout.Indent - */ -pv.Layout.Indent.prototype.defaults = new pv.Layout.Indent() - .extend(pv.Layout.Hierarchy.prototype.defaults) - .depth(15) - .breadth(15); - -/** @private */ -pv.Layout.Indent.prototype.buildImplied = function(s) { - if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return; - - var nodes = s.nodes, - bspace = s.breadth, - dspace = s.depth, - ax = 0, - ay = 0; - - /** @private */ - function position(n, breadth, depth) { - n.x = ax + depth++ * dspace; - n.y = ay + breadth++ * bspace; - n.midAngle = 0; - for (var c = n.firstChild; c; c = c.nextSibling) { - breadth = position(c, breadth, depth); - } - return breadth; - } - - position(nodes[0], 1, 1); -}; -/** - * Constructs a new, empty circle-packing layout. Layouts are not typically - * constructed directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a hierarchical layout using circle-packing. The meaning of - * the exported mark prototypes changes slightly in the space-filling - * implementation:

    - * - *
  • node - for rendering nodes; typically a {@link pv.Dot}. - * - *

  • link - unsupported; undefined. Links are encoded implicitly - * in the arrangement of the space-filling nodes. - * - *

  • label - for rendering node labels; typically a - * {@link pv.Label}. - * - *
The pack layout support dynamic sizing for leaf nodes, if a - * {@link #size} psuedo-property is specified. The default size function returns - * 1, causing all leaf nodes to be sized equally, and all internal nodes to be - * sized by the number of leaf nodes they have as descendants. - * - *

The size function can be used in conjunction with the order property, - * which allows the nodes to the sorted by the computed size. Note: for sorting - * based on other data attributes, simply use the default null for the - * order property, and sort the nodes beforehand using the {@link pv.Dom} - * operator. - * - *

For more details on how to use this layout, see - * {@link pv.Layout.Hierarchy}. - * - * @extends pv.Layout.Hierarchy - * @see "Visualization of large hierarchical data by circle packing" by W. Wang, - * H. Wang, G. Dai, and H. Wang, ACM CHI 2006. - */ -pv.Layout.Pack = function() { - pv.Layout.Hierarchy.call(this); - - this.node - .shapeRadius(function(n) { return n.radius; }) - .strokeStyle("rgb(31, 119, 180)") - .fillStyle("rgba(31, 119, 180, .25)"); - - this.label - .textAlign("center"); - - /* Hide unsupported link. */ - delete this.link; -}; - -pv.Layout.Pack.prototype = pv.extend(pv.Layout.Hierarchy) - .property("spacing", Number) - .property("order", String); // ascending, descending, reverse, null - -/** - * Default properties for circle-packing layouts. The default spacing parameter - * is 1 and the default order is "ascending". - * - * @type pv.Layout.Pack - */ -pv.Layout.Pack.prototype.defaults = new pv.Layout.Pack() - .extend(pv.Layout.Hierarchy.prototype.defaults) - .spacing(1) - .order("ascending"); - -/** - * The spacing parameter; defaults to 1, which provides a little bit of padding - * between sibling nodes and the enclosing circle. Larger values increase the - * spacing, by making the sibling nodes smaller; a value of zero makes the leaf - * nodes as large as possible, with no padding on enclosing circles. - * - * @type number - * @name pv.Layout.Pack.prototype.spacing - */ - -/** - * The sibling node order. The default order is null, which means to - * use the sibling order specified by the nodes property as-is. A value of - * "ascending" will sort siblings in ascending order of size, while "descending" - * will do the reverse. For sorting based on data attributes other than size, - * use the default null for the order property, and sort the nodes - * beforehand using the {@link pv.Dom} operator. - * - * @see pv.Dom.Node#sort - * @type string - * @name pv.Layout.Pack.prototype.order - */ - -/** @private The default size function. */ -pv.Layout.Pack.prototype.$radius = function() { return 1; }; - -// TODO is it possible for spacing to operate in pixel space? -// Right now it appears to be multiples of the smallest radius. - -/** - * Specifies the sizing function. By default, a sizing function is disabled and - * all nodes are given constant size. The sizing function is invoked for each - * leaf node in the tree (passed to the constructor). - * - *

For example, if the tree data structure represents a file system, with - * files as leaf nodes, and each file has a bytes attribute, you can - * specify a size function as: - * - *

    .size(function(d) d.bytes)
- * - * As with other properties, a size function may specify additional arguments to - * access the data associated with the layout and any enclosing panels. - * - * @param {function} f the new sizing function. - * @returns {pv.Layout.Pack} this. - */ -pv.Layout.Pack.prototype.size = function(f) { - this.$radius = typeof f == "function" - ? function() { return Math.sqrt(f.apply(this, arguments)); } - : (f = Math.sqrt(f), function() { return f; }); - return this; -}; - -/** @private */ -pv.Layout.Pack.prototype.buildImplied = function(s) { - if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return; - - var that = this, - nodes = s.nodes, - root = nodes[0]; - - /** @private Compute the radii of the leaf nodes. */ - function radii(nodes) { - var stack = pv.Mark.stack; - stack.unshift(null); - for (var i = 0, n = nodes.length; i < n; i++) { - var c = nodes[i]; - if (!c.firstChild) { - c.radius = that.$radius.apply(that, (stack[0] = c, stack)); - } - } - stack.shift(); - } - - /** @private */ - function packTree(n) { - var nodes = []; - for (var c = n.firstChild; c; c = c.nextSibling) { - if (c.firstChild) c.radius = packTree(c); - c.n = c.p = c; - nodes.push(c); - } - - /* Sort. */ - switch (s.order) { - case "ascending": { - nodes.sort(function(a, b) { return a.radius - b.radius; }); - break; - } - case "descending": { - nodes.sort(function(a, b) { return b.radius - a.radius; }); - break; - } - case "reverse": nodes.reverse(); break; - } - - return packCircle(nodes); - } - - /** @private */ - function packCircle(nodes) { - var xMin = Infinity, - xMax = -Infinity, - yMin = Infinity, - yMax = -Infinity, - a, b, c, j, k; - - /** @private */ - function bound(n) { - xMin = Math.min(n.x - n.radius, xMin); - xMax = Math.max(n.x + n.radius, xMax); - yMin = Math.min(n.y - n.radius, yMin); - yMax = Math.max(n.y + n.radius, yMax); - } - - /** @private */ - function insert(a, b) { - var c = a.n; - a.n = b; - b.p = a; - b.n = c; - c.p = b; - } - - /** @private */ - function splice(a, b) { - a.n = b; - b.p = a; - } - - /** @private */ - function intersects(a, b) { - var dx = b.x - a.x, - dy = b.y - a.y, - dr = a.radius + b.radius; - return (dr * dr - dx * dx - dy * dy) > .001; // within epsilon - } - - /* Create first node. */ - a = nodes[0]; - a.x = -a.radius; - a.y = 0; - bound(a); - - /* Create second node. */ - if (nodes.length > 1) { - b = nodes[1]; - b.x = b.radius; - b.y = 0; - bound(b); - - /* Create third node and build chain. */ - if (nodes.length > 2) { - c = nodes[2]; - place(a, b, c); - bound(c); - insert(a, c); - a.p = c; - insert(c, b); - b = a.n; - - /* Now iterate through the rest. */ - for (var i = 3; i < nodes.length; i++) { - place(a, b, c = nodes[i]); - - /* Search for the closest intersection. */ - var isect = 0, s1 = 1, s2 = 1; - for (j = b.n; j != b; j = j.n, s1++) { - if (intersects(j, c)) { - isect = 1; - break; - } - } - if (isect == 1) { - for (k = a.p; k != j.p; k = k.p, s2++) { - if (intersects(k, c)) { - if (s2 < s1) { - isect = -1; - j = k; - } - break; - } - } - } - - /* Update node chain. */ - if (isect == 0) { - insert(a, c); - b = c; - bound(c); - } else if (isect > 0) { - splice(a, j); - b = j; - i--; - } else if (isect < 0) { - splice(j, b); - a = j; - i--; - } - } - } - } - - /* Re-center the circles and return the encompassing radius. */ - var cx = (xMin + xMax) / 2, - cy = (yMin + yMax) / 2, - cr = 0; - for (var i = 0; i < nodes.length; i++) { - var n = nodes[i]; - n.x -= cx; - n.y -= cy; - cr = Math.max(cr, n.radius + Math.sqrt(n.x * n.x + n.y * n.y)); - } - return cr + s.spacing; - } - - /** @private */ - function place(a, b, c) { - var da = b.radius + c.radius, - db = a.radius + c.radius, - dx = b.x - a.x, - dy = b.y - a.y, - dc = Math.sqrt(dx * dx + dy * dy), - cos = (db * db + dc * dc - da * da) / (2 * db * dc), - theta = Math.acos(cos), - x = cos * db, - h = Math.sin(theta) * db; - dx /= dc; - dy /= dc; - c.x = a.x + x * dx + h * dy; - c.y = a.y + x * dy - h * dx; - } - - /** @private */ - function transform(n, x, y, k) { - for (var c = n.firstChild; c; c = c.nextSibling) { - c.x += n.x; - c.y += n.y; - transform(c, x, y, k); - } - n.x = x + k * n.x; - n.y = y + k * n.y; - n.radius *= k; - } - - radii(nodes); - - /* Recursively compute the layout. */ - root.x = 0; - root.y = 0; - root.radius = packTree(root); - - var w = this.width(), - h = this.height(), - k = 1 / Math.max(2 * root.radius / w, 2 * root.radius / h); - transform(root, w / 2, h / 2, k); -}; -/** - * Constructs a new, empty force-directed layout. Layouts are not typically - * constructed directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements force-directed network layout as a node-link diagram. This - * layout uses the Fruchterman-Reingold algorithm, which applies an attractive - * spring force between neighboring nodes, and a repulsive electrical charge - * force between all nodes. An additional drag force improves stability of the - * simulation. See {@link pv.Force.spring}, {@link pv.Force.drag} and {@link - * pv.Force.charge} for more details; note that the n-body charge force is - * approximated using the Barnes-Hut algorithm. - * - *

This layout is implemented on top of {@link pv.Simulation}, which can be - * used directly for more control over simulation parameters. The simulation - * uses Position Verlet integration, which does not compute velocities - * explicitly, but allows for easy geometric constraints, such as bounding the - * nodes within the layout panel. Many of the configuration properties supported - * by this layout are simply passed through to the underlying forces and - * constraints of the simulation. - * - *

Force layouts are typically interactive. The gradual movement of the nodes - * as they stabilize to a local stress minimum can help reveal the structure of - * the network, as can {@link pv.Behavior.drag}, which allows the user to pick - * up nodes and reposition them while the physics simulation continues. This - * layout can also be used with pan & zoom behaviors for interaction. - * - *

To facilitate interaction, this layout by default automatically re-renders - * using a setInterval every 42 milliseconds. This can be disabled via - * the iterations property, which if non-null specifies the number of - * simulation iterations to run before the force-directed layout is finalized. - * Be careful not to use too high an iteration count, as this can lead to an - * annoying delay on page load. - * - *

As with other network layouts, the network data can be updated - * dynamically, provided the property cache is reset. See - * {@link pv.Layout.Network} for details. New nodes are initialized with random - * positions near the center. Alternatively, positions can be specified manually - * by setting the x and y attributes on nodes. - * - * @extends pv.Layout.Network - * @see "Graph Drawing by Force-directed Placement" by T. Fruchterman & - * E. Reingold, Software--Practice & Experience, November 1991. - */ -pv.Layout.Force = function() { - pv.Layout.Network.call(this); - - /* Force-directed graphs can be messy, so reduce the link width. */ - this.link.lineWidth(function(d, p) { return Math.sqrt(p.linkValue) * 1.5; }); - this.label.textAlign("center"); -}; - -pv.Layout.Force.prototype = pv.extend(pv.Layout.Network) - .property("bound", Boolean) - .property("iterations", Number) - .property("dragConstant", Number) - .property("chargeConstant", Number) - .property("chargeMinDistance", Number) - .property("chargeMaxDistance", Number) - .property("chargeTheta", Number) - .property("springConstant", Number) - .property("springDamping", Number) - .property("springLength", Number); - -/** - * The bound parameter; true if nodes should be constrained within the layout - * panel. Bounding is disabled by default. Currently the layout does not observe - * the radius of the nodes; strictly speaking, only the center of the node is - * constrained to be within the panel, with an additional 6-pixel offset for - * padding. A future enhancement could extend the bound constraint to observe - * the node's radius, which would also support bounding for variable-size nodes. - * - *

Note that if this layout is used in conjunction with pan & zoom - * behaviors, those behaviors should have their bound parameter set to the same - * value. - * - * @type boolean - * @name pv.Layout.Force.prototype.bound - */ - -/** - * The number of simulation iterations to run, or null if this layout is - * interactive. Force-directed layouts are interactive by default, using a - * setInterval to advance the physics simulation and re-render - * automatically. - * - * @type number - * @name pv.Layout.Force.prototype.iterations - */ - -/** - * The drag constant, in the range [0,1]. A value of 0 means no drag (a - * perfectly frictionless environment), while a value of 1 means friction - * immediately cancels all momentum. The default value is 0.1, which provides a - * minimum amount of drag that helps stabilize bouncy springs; lower values may - * result in excessive bounciness, while higher values cause the simulation to - * take longer to converge. - * - * @type number - * @name pv.Layout.Force.prototype.dragConstant - * @see pv.Force.drag#constant - */ - -/** - * The charge constant, which should be a negative number. The default value is - * -40; more negative values will result in a stronger repulsive force, which - * may lead to faster convergence at the risk of instability. Too strong - * repulsive charge forces can cause comparatively weak springs to be stretched - * well beyond their rest length, emphasizing global structure over local - * structure. A nonnegative value will break the Fruchterman-Reingold algorithm, - * and is for entertainment purposes only. - * - * @type number - * @name pv.Layout.Force.prototype.chargeConstant - * @see pv.Force.charge#constant - */ - -/** - * The minimum distance at which charge forces are applied. The default minimum - * distance of 2 avoids applying forces that are two strong; because the physics - * simulation is run at discrete time intervals, it is possible for two same- - * charged particles to become very close or even a singularity! Since the - * charge force is inversely proportional to the square of the distance, very - * small distances can break the simulation. - * - *

In rare cases, two particles can become stuck on top of each other, as a - * minimum distance threshold will prevent the charge force from repelling them. - * However, this occurs very rarely because other forces and momentum typically - * cause the particles to become separated again, at which point the repulsive - * charge force kicks in. - * - * @type number - * @name pv.Layout.Force.prototype.chargeMinDistance - * @see pv.Force.charge#domain - */ - -/** - * The maximum distance at which charge forces are applied. This improves - * performance by ignoring weak charge forces at great distances. Note that this - * parameter is partly redundant, as the Barnes-Hut algorithm for n-body forces - * already improves performance for far-away particles through approximation. - * - * @type number - * @name pv.Layout.Force.prototype.chargeMaxDistance - * @see pv.Force.charge#domain - */ - -/** - * The Barnes-Hut approximation factor. The Barnes-Hut approximation criterion - * is the ratio of the size of the quadtree node to the distance from the point - * to the node's center of mass is beneath some threshold. The default value is - * 0.9. - * - * @type number - * @name pv.Layout.Force.prototype.chargeTheta - * @see pv.Force.charge#theta - */ - -/** - * The spring constant, which should be a positive number. The default value is - * 0.1; greater values will result in a stronger attractive force, which may - * lead to faster convergence at the risk of instability. Too strong spring - * forces can cause comparatively weak charge forces to be ignored, emphasizing - * local structure over global structure. A nonpositive value will break the - * Fruchterman-Reingold algorithm, and is for entertainment purposes only. - * - *

The spring tension is automatically normalized using the inverse square - * root of the maximum link degree of attached nodes. - * - * @type number - * @name pv.Layout.Force.prototype.springConstant - * @see pv.Force.spring#constant - */ - -/** - * The spring damping factor, in the range [0,1]. Damping functions identically - * to drag forces, damping spring bounciness by applying a force in the opposite - * direction of attached nodes' velocities. The default value is 0.3. - * - *

The spring damping is automatically normalized using the inverse square - * root of the maximum link degree of attached nodes. - * - * @type number - * @name pv.Layout.Force.prototype.springDamping - * @see pv.Force.spring#damping - */ - -/** - * The spring rest length. The default value is 20 pixels. Larger values may be - * appropriate if the layout panel is larger, or if the nodes are rendered - * larger than the default dot size of 20. - * - * @type number - * @name pv.Layout.Force.prototype.springLength - * @see pv.Force.spring#length - */ - -/** - * Default properties for force-directed layouts. The default drag constant is - * 0.1, the default charge constant is -40 (with a domain of [2, 500] and theta - * of 0.9), and the default spring constant is 0.1 (with a damping of 0.3 and a - * rest length of 20). - * - * @type pv.Layout.Force - */ -pv.Layout.Force.prototype.defaults = new pv.Layout.Force() - .extend(pv.Layout.Network.prototype.defaults) - .dragConstant(.1) - .chargeConstant(-40) - .chargeMinDistance(2) - .chargeMaxDistance(500) - .chargeTheta(.9) - .springConstant(.1) - .springDamping(.3) - .springLength(20); - -/** @private Initialize the physics simulation. */ -pv.Layout.Force.prototype.buildImplied = function(s) { - - /* Any cached interactive layouts need to be rebound for the timer. */ - if (pv.Layout.Network.prototype.buildImplied.call(this, s)) { - var f = s.$force; - if (f) { - f.next = this.binds.$force; - this.binds.$force = f; - } - return; - } - - var that = this, - nodes = s.nodes, - links = s.links, - k = s.iterations, - w = s.width, - h = s.height; - - /* Initialize positions randomly near the center. */ - for (var i = 0, n; i < nodes.length; i++) { - n = nodes[i]; - if (isNaN(n.x)) n.x = w / 2 + 40 * Math.random() - 20; - if (isNaN(n.y)) n.y = h / 2 + 40 * Math.random() - 20; - } - - /* Initialize the simulation. */ - var sim = pv.simulation(nodes); - - /* Drag force. */ - sim.force(pv.Force.drag(s.dragConstant)); - - /* Charge (repelling) force. */ - sim.force(pv.Force.charge(s.chargeConstant) - .domain(s.chargeMinDistance, s.chargeMaxDistance) - .theta(s.chargeTheta)); - - /* Spring (attracting) force. */ - sim.force(pv.Force.spring(s.springConstant) - .damping(s.springDamping) - .length(s.springLength) - .links(links)); - - /* Position constraint (for interactive dragging). */ - sim.constraint(pv.Constraint.position()); - - /* Optionally add bound constraint. TODO: better padding. */ - if (s.bound) { - sim.constraint(pv.Constraint.bound().x(6, w - 6).y(6, h - 6)); - } - - /** @private Returns the speed of the given node, to determine cooling. */ - function speed(n) { - return n.fix ? 1 : n.vx * n.vx + n.vy * n.vy; - } - - /* - * If the iterations property is null (the default), the layout is - * interactive. The simulation is run until the fastest particle drops below - * an arbitrary minimum speed. Although the timer keeps firing, this speed - * calculation is fast so there is minimal CPU overhead. Note: if a particle - * is fixed for interactivity, treat this as a high speed and resume - * simulation. - */ - if (k == null) { - sim.step(); // compute initial previous velocities - sim.step(); // compute initial velocities - - /* Add the simulation state to the bound list. */ - var force = s.$force = this.binds.$force = { - next: this.binds.$force, - nodes: nodes, - min: 1e-4 * (links.length + 1), - sim: sim - }; - - /* Start the timer, if not already started. */ - if (!this.$timer) this.$timer = setInterval(function() { - var render = false; - for (var f = that.binds.$force; f; f = f.next) { - if (pv.max(f.nodes, speed) > f.min) { - f.sim.step(); - render = true; - } - } - if (render) that.render(); - }, 42); - } else for (var i = 0; i < k; i++) { - sim.step(); - } -}; -/** - * Constructs a new, empty cluster layout. Layouts are not typically - * constructed directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a hierarchical layout using the cluster (or dendrogram) - * algorithm. This layout provides both node-link and space-filling - * implementations of cluster diagrams. In many ways it is similar to - * {@link pv.Layout.Partition}, except that leaf nodes are positioned at maximum - * depth, and the depth of internal nodes is based on their distance from their - * deepest descendant, rather than their distance from the root. - * - *

The cluster layout supports a "group" property, which if true causes - * siblings to be positioned closer together than unrelated nodes at the same - * depth. Unlike the partition layout, this layout does not support dynamic - * sizing for leaf nodes; all leaf nodes are the same size. - * - *

For more details on how to use this layout, see - * {@link pv.Layout.Hierarchy}. - * - * @see pv.Layout.Cluster.Fill - * @extends pv.Layout.Hierarchy - */ -pv.Layout.Cluster = function() { - pv.Layout.Hierarchy.call(this); - var interpolate, // cached interpolate - buildImplied = this.buildImplied; - - /** @private Cache layout state to optimize properties. */ - this.buildImplied = function(s) { - buildImplied.call(this, s); - interpolate - = /^(top|bottom)$/.test(s.orient) ? "step-before" - : /^(left|right)$/.test(s.orient) ? "step-after" - : "linear"; - }; - - this.link.interpolate(function() { return interpolate; }); -}; - -pv.Layout.Cluster.prototype = pv.extend(pv.Layout.Hierarchy) - .property("group", Number) - .property("orient", String) - .property("innerRadius", Number) - .property("outerRadius", Number); - -/** - * The group parameter; defaults to 0, disabling grouping of siblings. If this - * parameter is set to a positive number (or true, which is equivalent to 1), - * then additional space will be allotted between sibling groups. In other - * words, siblings (nodes that share the same parent) will be positioned more - * closely than nodes at the same depth that do not share a parent. - * - * @type number - * @name pv.Layout.Cluster.prototype.group - */ - -/** - * The orientation. The default orientation is "top", which means that the root - * node is placed on the top edge, leaf nodes appear on the bottom edge, and - * internal nodes are in-between. The following orientations are supported:

    - * - *
  • left - left-to-right. - *
  • right - right-to-left. - *
  • top - top-to-bottom. - *
  • bottom - bottom-to-top. - *
  • radial - radially, with the root at the center.
- * - * @type string - * @name pv.Layout.Cluster.prototype.orient - */ - -/** - * The inner radius; defaults to 0. This property applies only to radial - * orientations, and can be used to compress the layout radially. Note that for - * the node-link implementation, the root node is always at the center, - * regardless of the value of this property; this property only affects internal - * and leaf nodes. For the space-filling implementation, a non-zero value of - * this property will result in the root node represented as a ring rather than - * a circle. - * - * @type number - * @name pv.Layout.Cluster.prototype.innerRadius - */ - -/** - * The outer radius; defaults to fill the containing panel, based on the height - * and width of the layout. If the layout has no height and width specified, it - * will extend to fill the enclosing panel. - * - * @type number - * @name pv.Layout.Cluster.prototype.outerRadius - */ - -/** - * Defaults for cluster layouts. The default group parameter is 0 and the - * default orientation is "top". - * - * @type pv.Layout.Cluster - */ -pv.Layout.Cluster.prototype.defaults = new pv.Layout.Cluster() - .extend(pv.Layout.Hierarchy.prototype.defaults) - .group(0) - .orient("top"); - -/** @private */ -pv.Layout.Cluster.prototype.buildImplied = function(s) { - if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return; - - var root = s.nodes[0], - group = s.group, - breadth, - depth, - leafCount = 0, - leafIndex = .5 - group / 2; - - /* Count the leaf nodes and compute the depth of descendants. */ - var p = undefined; - root.visitAfter(function(n) { - if (n.firstChild) { - n.depth = 1 + pv.max(n.childNodes, function(n) { return n.depth; }); - } else { - if (group && (p != n.parentNode)) { - p = n.parentNode; - leafCount += group; - } - leafCount++; - n.depth = 0; - } - }); - breadth = 1 / leafCount; - depth = 1 / root.depth; - - /* Compute the unit breadth and depth of each node. */ - var p = undefined; - root.visitAfter(function(n) { - if (n.firstChild) { - n.breadth = pv.mean(n.childNodes, function(n) { return n.breadth; }); - } else { - if (group && (p != n.parentNode)) { - p = n.parentNode; - leafIndex += group; - } - n.breadth = breadth * leafIndex++; - } - n.depth = 1 - n.depth * depth; - }); - - /* Compute breadth and depth ranges for space-filling layouts. */ - root.visitAfter(function(n) { - n.minBreadth = n.firstChild - ? n.firstChild.minBreadth - : (n.breadth - breadth / 2); - n.maxBreadth = n.firstChild - ? n.lastChild.maxBreadth - : (n.breadth + breadth / 2); - }); - root.visitBefore(function(n) { - n.minDepth = n.parentNode - ? n.parentNode.maxDepth - : 0; - n.maxDepth = n.parentNode - ? (n.depth + root.depth) - : (n.minDepth + 2 * root.depth); - }); - root.minDepth = -depth; - - pv.Layout.Hierarchy.NodeLink.buildImplied.call(this, s); -}; - -/** - * Constructs a new, empty space-filling cluster layout. Layouts are not - * typically constructed directly; instead, they are added to an existing panel - * via {@link pv.Mark#add}. - * - * @class A variant of cluster layout that is space-filling. The meaning of the - * exported mark prototypes changes slightly in the space-filling - * implementation:
    - * - *
  • node - for rendering nodes; typically a {@link pv.Bar} for - * non-radial orientations, and a {@link pv.Wedge} for radial orientations. - * - *

  • link - unsupported; undefined. Links are encoded implicitly - * in the arrangement of the space-filling nodes. - * - *

  • label - for rendering node labels; typically a - * {@link pv.Label}. - * - *
For more details on how to use this layout, see - * {@link pv.Layout.Cluster}. - * - * @extends pv.Layout.Cluster - */ -pv.Layout.Cluster.Fill = function() { - pv.Layout.Cluster.call(this); - pv.Layout.Hierarchy.Fill.constructor.call(this); -}; - -pv.Layout.Cluster.Fill.prototype = pv.extend(pv.Layout.Cluster); - -/** @private */ -pv.Layout.Cluster.Fill.prototype.buildImplied = function(s) { - if (pv.Layout.Cluster.prototype.buildImplied.call(this, s)) return; - pv.Layout.Hierarchy.Fill.buildImplied.call(this, s); -}; -/** - * Constructs a new, empty partition layout. Layouts are not typically - * constructed directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a hierarchical layout using the partition (or sunburst, - * icicle) algorithm. This layout provides both node-link and space-filling - * implementations of partition diagrams. In many ways it is similar to - * {@link pv.Layout.Cluster}, except that leaf nodes are positioned based on - * their distance from the root. - * - *

The partition layout support dynamic sizing for leaf nodes, if a - * {@link #size} psuedo-property is specified. The default size function returns - * 1, causing all leaf nodes to be sized equally, and all internal nodes to be - * sized by the number of leaf nodes they have as descendants. - * - *

The size function can be used in conjunction with the order property, - * which allows the nodes to the sorted by the computed size. Note: for sorting - * based on other data attributes, simply use the default null for the - * order property, and sort the nodes beforehand using the {@link pv.Dom} - * operator. - * - *

For more details on how to use this layout, see - * {@link pv.Layout.Hierarchy}. - * - * @see pv.Layout.Partition.Fill - * @extends pv.Layout.Hierarchy - */ -pv.Layout.Partition = function() { - pv.Layout.Hierarchy.call(this); -}; - -pv.Layout.Partition.prototype = pv.extend(pv.Layout.Hierarchy) - .property("order", String) // null, ascending, descending? - .property("orient", String) // top, left, right, bottom, radial - .property("innerRadius", Number) - .property("outerRadius", Number); - -/** - * The sibling node order. The default order is null, which means to - * use the sibling order specified by the nodes property as-is. A value of - * "ascending" will sort siblings in ascending order of size, while "descending" - * will do the reverse. For sorting based on data attributes other than size, - * use the default null for the order property, and sort the nodes - * beforehand using the {@link pv.Dom} operator. - * - * @see pv.Dom.Node#sort - * @type string - * @name pv.Layout.Partition.prototype.order - */ - -/** - * The orientation. The default orientation is "top", which means that the root - * node is placed on the top edge, leaf nodes appear at the bottom, and internal - * nodes are in-between. The following orientations are supported:

    - * - *
  • left - left-to-right. - *
  • right - right-to-left. - *
  • top - top-to-bottom. - *
  • bottom - bottom-to-top. - *
  • radial - radially, with the root at the center.
- * - * @type string - * @name pv.Layout.Partition.prototype.orient - */ - -/** - * The inner radius; defaults to 0. This property applies only to radial - * orientations, and can be used to compress the layout radially. Note that for - * the node-link implementation, the root node is always at the center, - * regardless of the value of this property; this property only affects internal - * and leaf nodes. For the space-filling implementation, a non-zero value of - * this property will result in the root node represented as a ring rather than - * a circle. - * - * @type number - * @name pv.Layout.Partition.prototype.innerRadius - */ - -/** - * The outer radius; defaults to fill the containing panel, based on the height - * and width of the layout. If the layout has no height and width specified, it - * will extend to fill the enclosing panel. - * - * @type number - * @name pv.Layout.Partition.prototype.outerRadius - */ - -/** - * Default properties for partition layouts. The default orientation is "top". - * - * @type pv.Layout.Partition - */ -pv.Layout.Partition.prototype.defaults = new pv.Layout.Partition() - .extend(pv.Layout.Hierarchy.prototype.defaults) - .orient("top"); - -/** @private */ -pv.Layout.Partition.prototype.$size = function() { return 1; }; - -/** - * Specifies the sizing function. By default, a sizing function is disabled and - * all nodes are given constant size. The sizing function is invoked for each - * leaf node in the tree (passed to the constructor). - * - *

For example, if the tree data structure represents a file system, with - * files as leaf nodes, and each file has a bytes attribute, you can - * specify a size function as: - * - *

    .size(function(d) d.bytes)
- * - * As with other properties, a size function may specify additional arguments to - * access the data associated with the layout and any enclosing panels. - * - * @param {function} f the new sizing function. - * @returns {pv.Layout.Partition} this. - */ -pv.Layout.Partition.prototype.size = function(f) { - this.$size = f; - return this; -}; - -/** @private */ -pv.Layout.Partition.prototype.buildImplied = function(s) { - if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return; - - var that = this, - root = s.nodes[0], - stack = pv.Mark.stack, - maxDepth = 0; - - /* Recursively compute the tree depth and node size. */ - stack.unshift(null); - root.visitAfter(function(n, depth) { - if (depth > maxDepth) maxDepth = depth; - n.size = n.firstChild - ? pv.sum(n.childNodes, function(n) { return n.size; }) - : that.$size.apply(that, (stack[0] = n, stack)); - }); - stack.shift(); - - /* Order */ - switch (s.order) { - case "ascending": root.sort(function(a, b) { return a.size - b.size; }); break; - case "descending": root.sort(function(b, a) { return a.size - b.size; }); break; - } - - /* Compute the unit breadth and depth of each node. */ - root.minBreadth = 0; - root.breadth = .5; - root.maxBreadth = 1; - - root.visitBefore(function(n) { - var b = n.minBreadth, - s = n.maxBreadth - b; // span - - for (var c = n.firstChild; c; c = c.nextSibling) { - c.minBreadth = b; - b += (c.size / n.size) * s; - c.maxBreadth = b; - - c.breadth = (b + c.minBreadth) / 2; - } - }); - - root.visitAfter(function(n, depth) { - n.minDepth = (depth - 1) / maxDepth; - n.maxDepth = (n.depth = depth / maxDepth); - }); - - pv.Layout.Hierarchy.NodeLink.buildImplied.call(this, s); -}; - -/** - * Constructs a new, empty space-filling partition layout. Layouts are not - * typically constructed directly; instead, they are added to an existing panel - * via {@link pv.Mark#add}. - * - * @class A variant of partition layout that is space-filling. The meaning of - * the exported mark prototypes changes slightly in the space-filling - * implementation:
    - * - *
  • node - for rendering nodes; typically a {@link pv.Bar} for - * non-radial orientations, and a {@link pv.Wedge} for radial orientations. - * - *

  • link - unsupported; undefined. Links are encoded implicitly - * in the arrangement of the space-filling nodes. - * - *

  • label - for rendering node labels; typically a - * {@link pv.Label}. - * - *
For more details on how to use this layout, see - * {@link pv.Layout.Partition}. - * - * @extends pv.Layout.Partition - */ -pv.Layout.Partition.Fill = function() { - pv.Layout.Partition.call(this); - pv.Layout.Hierarchy.Fill.constructor.call(this); -}; - -pv.Layout.Partition.Fill.prototype = pv.extend(pv.Layout.Partition); - -/** @private */ -pv.Layout.Partition.Fill.prototype.buildImplied = function(s) { - if (pv.Layout.Partition.prototype.buildImplied.call(this, s)) return; - pv.Layout.Hierarchy.Fill.buildImplied.call(this, s); -}; -/** - * Constructs a new, empty arc layout. Layouts are not typically constructed - * directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a layout for arc diagrams. An arc diagram is a network - * visualization with a one-dimensional layout of nodes, using circular arcs to - * render links between nodes. For undirected networks, arcs are rendering on a - * single side; this makes arc diagrams useful as annotations to other - * two-dimensional network layouts, such as rollup, matrix or table layouts. For - * directed networks, links in opposite directions can be rendered on opposite - * sides using directed(true). - * - *

Arc layouts are particularly sensitive to node ordering; for best results, - * order the nodes such that related nodes are close to each other. A poor - * (e.g., random) order may result in large arcs with crossovers that impede - * visual processing. A future improvement to this layout may include automatic - * reordering using, e.g., spectral graph layout or simulated annealing. - * - *

This visualization technique is related to that developed by - * M. Wattenberg, "Arc - * Diagrams: Visualizing Structure in Strings" in IEEE InfoVis, 2002. - * However, this implementation is limited to simple node-link networks, as - * opposed to structures with hierarchical self-similarity (such as strings). - * - *

As with other network layouts, three mark prototypes are provided:

    - * - *
  • node - for rendering nodes; typically a {@link pv.Dot}. - *
  • link - for rendering links; typically a {@link pv.Line}. - *
  • label - for rendering node labels; typically a {@link pv.Label}. - * - *
For more details on how this layout is structured and can be customized, - * see {@link pv.Layout.Network}. - * - * @extends pv.Layout.Network - **/ -pv.Layout.Arc = function() { - pv.Layout.Network.call(this); - var interpolate, // cached interpolate - directed, // cached directed - reverse, // cached reverse - buildImplied = this.buildImplied; - - /** @private Cache layout state to optimize properties. */ - this.buildImplied = function(s) { - buildImplied.call(this, s); - directed = s.directed; - interpolate = s.orient == "radial" ? "linear" : "polar"; - reverse = s.orient == "right" || s.orient == "top"; - }; - - /* Override link properties to handle directedness and orientation. */ - this.link - .data(function(p) { - var s = p.sourceNode, t = p.targetNode; - return reverse != (directed || (s.breadth < t.breadth)) ? [s, t] : [t, s]; - }) - .interpolate(function() { return interpolate; }); -}; - -pv.Layout.Arc.prototype = pv.extend(pv.Layout.Network) - .property("orient", String) - .property("directed", Boolean); - -/** - * Default properties for arc layouts. By default, the orientation is "bottom". - * - * @type pv.Layout.Arc - */ -pv.Layout.Arc.prototype.defaults = new pv.Layout.Arc() - .extend(pv.Layout.Network.prototype.defaults) - .orient("bottom"); - -/** - * Specifies an optional sort function. The sort function follows the same - * comparator contract required by {@link pv.Dom.Node#sort}. Specifying a sort - * function provides an alternative to sort the nodes as they are specified by - * the nodes property; the main advantage of doing this is that the - * comparator function can access implicit fields populated by the network - * layout, such as the linkDegree. - * - *

Note that arc diagrams are particularly sensitive to order. This is - * referred to as the seriation problem, and many different techniques exist to - * find good node orders that emphasize clusters, such as spectral layout and - * simulated annealing. - * - * @param {function} f comparator function for nodes. - * @returns {pv.Layout.Arc} this. - */ -pv.Layout.Arc.prototype.sort = function(f) { - this.$sort = f; - return this; -}; - -/** @private Populates the x, y and angle attributes on the nodes. */ -pv.Layout.Arc.prototype.buildImplied = function(s) { - if (pv.Layout.Network.prototype.buildImplied.call(this, s)) return; - - var nodes = s.nodes, - orient = s.orient, - sort = this.$sort, - index = pv.range(nodes.length), - w = s.width, - h = s.height, - r = Math.min(w, h) / 2; - - /* Sort the nodes. */ - if (sort) index.sort(function(a, b) { return sort(nodes[a], nodes[b]); }); - - /** @private Returns the mid-angle, given the breadth. */ - function midAngle(b) { - switch (orient) { - case "top": return -Math.PI / 2; - case "bottom": return Math.PI / 2; - case "left": return Math.PI; - case "right": return 0; - case "radial": return (b - .25) * 2 * Math.PI; - } - } - - /** @private Returns the x-position, given the breadth. */ - function x(b) { - switch (orient) { - case "top": - case "bottom": return b * w; - case "left": return 0; - case "right": return w; - case "radial": return w / 2 + r * Math.cos(midAngle(b)); - } - } - - /** @private Returns the y-position, given the breadth. */ - function y(b) { - switch (orient) { - case "top": return 0; - case "bottom": return h; - case "left": - case "right": return b * h; - case "radial": return h / 2 + r * Math.sin(midAngle(b)); - } - } - - /* Populate the x, y and mid-angle attributes. */ - for (var i = 0; i < nodes.length; i++) { - var n = nodes[index[i]], b = n.breadth = (i + .5) / nodes.length; - n.x = x(b); - n.y = y(b); - n.midAngle = midAngle(b); - } -}; - -/** - * The orientation. The default orientation is "left", which means that nodes - * will be positioned from left-to-right in the order they are specified in the - * nodes property. The following orientations are supported:

    - * - *
  • left - left-to-right. - *
  • right - right-to-left. - *
  • top - top-to-bottom. - *
  • bottom - bottom-to-top. - *
  • radial - radially, starting at 12 o'clock and proceeding clockwise.
- * - * @type string - * @name pv.Layout.Arc.prototype.orient - */ - -/** - * Whether this arc digram is directed (bidirectional); only applies to - * non-radial orientations. By default, arc digrams are undirected, such that - * all arcs appear on one side. If the arc digram is directed, then forward - * links are drawn on the conventional side (the same as as undirected - * links--right, left, bottom and top for left, right, top and bottom, - * respectively), while reverse links are drawn on the opposite side. - * - * @type boolean - * @name pv.Layout.Arc.prototype.directed - */ -/** - * Constructs a new, empty horizon layout. Layouts are not typically constructed - * directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a horizon layout, which is a variation of a single-series - * area chart where the area is folded into multiple bands. Color is used to - * encode band, allowing the size of the chart to be reduced significantly - * without impeding readability. This layout algorithm is based on the work of - * J. Heer, N. Kong and M. Agrawala in "Sizing - * the Horizon: The Effects of Chart Size and Layering on the Graphical - * Perception of Time Series Visualizations", CHI 2009. - * - *

This layout exports a single band mark prototype, which is - * intended to be used with an area mark. The band mark is contained in a panel - * which is replicated per band (and for negative/positive bands). For example, - * to create a simple horizon graph given an array of numbers: - * - *

vis.add(pv.Layout.Horizon)
- *     .bands(n)
- *   .band.add(pv.Area)
- *     .data(data)
- *     .left(function() this.index * 35)
- *     .height(function(d) d * 40);
- * - * The layout can be further customized by changing the number of bands, and - * toggling whether the negative bands are mirrored or offset. (See the - * above-referenced paper for guidance.) - * - *

The fillStyle of the area can be overridden, though typically it - * is easier to customize the layout's behavior through the custom - * backgroundStyle, positiveStyle and negativeStyle - * properties. By default, the background is white, positive bands are blue, and - * negative bands are red. For the most accurate presentation, use fully-opaque - * colors of equal intensity for the negative and positive bands. - * - * @extends pv.Layout - */ -pv.Layout.Horizon = function() { - pv.Layout.call(this); - var that = this, - bands, // cached bands - mode, // cached mode - size, // cached height - fill, // cached background style - red, // cached negative color (ramp) - blue, // cached positive color (ramp) - buildImplied = this.buildImplied; - - /** @private Cache the layout state to optimize properties. */ - this.buildImplied = function(s) { - buildImplied.call(this, s); - bands = s.bands; - mode = s.mode; - size = Math.round((mode == "color" ? .5 : 1) * s.height); - fill = s.backgroundStyle; - red = pv.ramp(fill, s.negativeStyle).domain(0, bands); - blue = pv.ramp(fill, s.positiveStyle).domain(0, bands); - }; - - var bands = new pv.Panel() - .data(function() { return pv.range(bands * 2); }) - .overflow("hidden") - .height(function() { return size; }) - .top(function(i) { return mode == "color" ? (i & 1) * size : 0; }) - .fillStyle(function(i) { return i ? null : fill; }); - - /** - * The band prototype. This prototype is intended to be used with an Area - * mark to render the horizon bands. - * - * @type pv.Mark - * @name pv.Layout.Horizon.prototype.band - */ - this.band = new pv.Mark() - .top(function(d, i) { - return mode == "mirror" && i & 1 - ? (i + 1 >> 1) * size - : null; - }) - .bottom(function(d, i) { - return mode == "mirror" - ? (i & 1 ? null : (i + 1 >> 1) * -size) - : ((i & 1 || -1) * (i + 1 >> 1) * size); - }) - .fillStyle(function(d, i) { - return (i & 1 ? red : blue)((i >> 1) + 1); - }); - - this.band.add = function(type) { - return that.add(pv.Panel).extend(bands).add(type).extend(this); - }; -}; - -pv.Layout.Horizon.prototype = pv.extend(pv.Layout) - .property("bands", Number) - .property("mode", String) - .property("backgroundStyle", pv.color) - .property("positiveStyle", pv.color) - .property("negativeStyle", pv.color); - -/** - * Default properties for horizon layouts. By default, there are two bands, the - * mode is "offset", the background style is "white", the positive style is - * blue, negative style is red. - * - * @type pv.Layout.Horizon - */ -pv.Layout.Horizon.prototype.defaults = new pv.Layout.Horizon() - .extend(pv.Layout.prototype.defaults) - .bands(2) - .mode("offset") - .backgroundStyle("white") - .positiveStyle("#1f77b4") - .negativeStyle("#d62728"); - -/** - * The horizon mode: offset, mirror, or color. The default is "offset". - * - * @type string - * @name pv.Layout.Horizon.prototype.mode - */ - -/** - * The number of bands. Must be at least one. The default value is two. - * - * @type number - * @name pv.Layout.Horizon.prototype.bands - */ - -/** - * The positive band color; if non-null, the interior of positive bands are - * filled with the specified color. The default value of this property is blue. - * For accurate blending, this color should be fully opaque. - * - * @type pv.Color - * @name pv.Layout.Horizon.prototype.positiveStyle - */ - -/** - * The negative band color; if non-null, the interior of negative bands are - * filled with the specified color. The default value of this property is red. - * For accurate blending, this color should be fully opaque. - * - * @type pv.Color - * @name pv.Layout.Horizon.prototype.negativeStyle - */ - -/** - * The background color. The panel background is filled with the specified - * color, and the negative and positive bands are filled with an interpolated - * color between this color and the respective band color. The default value of - * this property is white. For accurate blending, this color should be fully - * opaque. - * - * @type pv.Color - * @name pv.Layout.Horizon.prototype.backgroundStyle - */ -/** - * Constructs a new, empty rollup network layout. Layouts are not typically - * constructed directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a network visualization using a node-link diagram where - * nodes are rolled up along two dimensions. This implementation is based on the - * "PivotGraph" designed by Martin Wattenberg: - * - *

The method is designed for graphs that are "multivariate", i.e., - * where each node is associated with several attributes. Unlike visualizations - * which emphasize global graph topology, PivotGraph uses a simple grid-based - * approach to focus on the relationship between node attributes & - * connections.
- * - * This layout requires two psuedo-properties to be specified, which assign node - * positions along the two dimensions {@link #x} and {@link #y}, corresponding - * to the left and top properties, respectively. Typically, these functions are - * specified using an {@link pv.Scale.ordinal}. Nodes that share the same - * position in x and y are "rolled up" into a meta-node, and - * similarly links are aggregated between meta-nodes. For example, to construct - * a rollup to analyze links by gender and affiliation, first define two ordinal - * scales: - * - *
var x = pv.Scale.ordinal(nodes, function(d) d.gender).split(0, w),
- *     y = pv.Scale.ordinal(nodes, function(d) d.aff).split(0, h);
- * - * Next, define the position psuedo-properties: - * - *
    .x(function(d) x(d.gender))
- *     .y(function(d) y(d.aff))
- * - * Linear and other quantitative scales can alternatively be used to position - * the nodes along either dimension. Note, however, that the rollup requires - * that the positions match exactly, and thus ordinal scales are recommended to - * avoid precision errors. - * - *

Note that because this layout provides a visualization of the rolled up - * graph, the data properties for the mark prototypes (node, - * link and label) are different from most other network - * layouts: they reference the rolled-up nodes and links, rather than the nodes - * and links of the full network. The underlying nodes and links for each - * rolled-up node and link can be accessed via the nodes and - * links attributes, respectively. The aggregated link values for - * rolled-up links can similarly be accessed via the linkValue - * attribute. - * - *

For undirected networks, links are duplicated in both directions. For - * directed networks, use directed(true). The graph is assumed to be - * undirected by default. - * - * @extends pv.Layout.Network - * @see "Visual Exploration of Multivariate Graphs" by M. Wattenberg, CHI 2006. - */ -pv.Layout.Rollup = function() { - pv.Layout.Network.call(this); - var that = this, - nodes, // cached rollup nodes - links, // cached rollup links - buildImplied = that.buildImplied; - - /** @private Cache layout state to optimize properties. */ - this.buildImplied = function(s) { - buildImplied.call(this, s); - nodes = s.$rollup.nodes; - links = s.$rollup.links; - }; - - /* Render rollup nodes. */ - this.node - .data(function() { return nodes; }) - .shapeSize(function(d) { return d.nodes.length * 20; }); - - /* Render rollup links. */ - this.link - .interpolate("polar") - .eccentricity(.8); - - this.link.add = function(type) { - return that.add(pv.Panel) - .data(function() { return links; }) - .add(type) - .extend(this); - }; -}; - -pv.Layout.Rollup.prototype = pv.extend(pv.Layout.Network) - .property("directed", Boolean); - -/** - * Whether the underlying network is directed. By default, the graph is assumed - * to be undirected, and links are rendered in both directions. If the network - * is directed, then forward links are drawn above the diagonal, while reverse - * links are drawn below. - * - * @type boolean - * @name pv.Layout.Rollup.prototype.directed - */ - -/** - * Specifies the x-position function used to rollup nodes. The rolled up - * nodes are positioned horizontally using the return values from the given - * function. Typically the function is specified as an ordinal scale. For - * single-dimension rollups, a constant value can be specified. - * - * @param {function} f the x-position function. - * @returns {pv.Layout.Rollup} this. - * @see pv.Scale.ordinal - */ -pv.Layout.Rollup.prototype.x = function(f) { - this.$x = pv.functor(f); - return this; -}; - -/** - * Specifies the y-position function used to rollup nodes. The rolled up - * nodes are positioned vertically using the return values from the given - * function. Typically the function is specified as an ordinal scale. For - * single-dimension rollups, a constant value can be specified. - * - * @param {function} f the y-position function. - * @returns {pv.Layout.Rollup} this. - * @see pv.Scale.ordinal - */ -pv.Layout.Rollup.prototype.y = function(f) { - this.$y = pv.functor(f); - return this; -}; - -/** @private */ -pv.Layout.Rollup.prototype.buildImplied = function(s) { - if (pv.Layout.Network.prototype.buildImplied.call(this, s)) return; - - var nodes = s.nodes, - links = s.links, - directed = s.directed, - n = nodes.length, - x = [], - y = [], - rnindex = 0, - rnodes = {}, - rlinks = {}; - - /** @private */ - function id(i) { - return x[i] + "," + y[i]; - } - - /* Iterate over the data, evaluating the x and y functions. */ - var stack = pv.Mark.stack, o = {parent: this}; - stack.unshift(null); - for (var i = 0; i < n; i++) { - o.index = i; - stack[0] = nodes[i]; - x[i] = this.$x.apply(o, stack); - y[i] = this.$y.apply(o, stack); - } - stack.shift(); - - /* Compute rollup nodes. */ - for (var i = 0; i < nodes.length; i++) { - var nodeId = id(i), - rn = rnodes[nodeId]; - if (!rn) { - rn = rnodes[nodeId] = pv.extend(nodes[i]); - rn.index = rnindex++; - rn.x = x[i]; - rn.y = y[i]; - rn.nodes = []; - } - rn.nodes.push(nodes[i]); - } - - /* Compute rollup links. */ - for (var i = 0; i < links.length; i++) { - var source = links[i].sourceNode, - target = links[i].targetNode, - rsource = rnodes[id(source.index)], - rtarget = rnodes[id(target.index)], - reverse = !directed && rsource.index > rtarget.index, - linkId = reverse - ? rtarget.index + "," + rsource.index - : rsource.index + "," + rtarget.index, - rl = rlinks[linkId]; - if (!rl) { - rl = rlinks[linkId] = { - sourceNode: rsource, - targetNode: rtarget, - linkValue: 0, - links: [] - }; - } - rl.links.push(links[i]); - rl.linkValue += links[i].linkValue; - } - - /* Export the rolled up nodes and links to the scene. */ - s.$rollup = { - nodes: pv.values(rnodes), - links: pv.values(rlinks) - }; -}; -/** - * Constructs a new, empty matrix network layout. Layouts are not typically - * constructed directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class Implements a network visualization using a matrix view. This is, in - * effect, a visualization of the graph's adjacency matrix: the cell at - * row i, column j, corresponds to the link from node i to - * node j. The fill color of each cell is binary by default, and - * corresponds to whether a link exists between the two nodes. If the underlying - * graph has links with variable values, the fillStyle property can be - * substited to use an appropriate color function, such as {@link pv.ramp}. - * - *

For undirected networks, the matrix is symmetric around the diagonal. For - * directed networks, links in opposite directions can be rendered on opposite - * sides of the diagonal using directed(true). The graph is assumed to - * be undirected by default. - * - *

The mark prototypes for this network layout are slightly different than - * other implementations:

    - * - *
  • node - unsupported; undefined. No mark is needed to visualize - * nodes directly, as the nodes are implicit in the location (rows and columns) - * of the links. - * - *

  • link - for rendering links; typically a {@link pv.Bar}. The - * link mark is added directly to the layout, with the data property defined as - * all possible pairs of nodes. Each pair is represented as a - * {@link pv.Network.Layout.Link}, though the linkValue attribute may - * be 0 if no link exists in the graph. - * - *

  • label - for rendering node labels; typically a - * {@link pv.Label}. The label mark is added directly to the layout, with the - * data property defined via the layout's nodes property; note, - * however, that the nodes are duplicated so as to provide a label across the - * top and down the side. Properties such as strokeStyle and - * fillStyle can be overridden to compute properties from node data - * dynamically. - * - *
For more details on how to use this layout, see - * {@link pv.Layout.Network}. - * - * @extends pv.Layout.Network - */ -pv.Layout.Matrix = function() { - pv.Layout.Network.call(this); - var that = this, - n, // cached matrix size - dx, // cached cell width - dy, // cached cell height - labels, // cached labels (array of strings) - pairs, // cached pairs (array of links) - buildImplied = that.buildImplied; - - /** @private Cache layout state to optimize properties. */ - this.buildImplied = function(s) { - buildImplied.call(this, s); - n = s.nodes.length; - dx = s.width / n; - dy = s.height / n; - labels = s.$matrix.labels; - pairs = s.$matrix.pairs; - }; - - /* Links are all pairs of nodes. */ - this.link - .data(function() { return pairs; }) - .left(function() { return dx * (this.index % n); }) - .top(function() { return dy * Math.floor(this.index / n); }) - .width(function() { return dx; }) - .height(function() { return dy; }) - .lineWidth(1.5) - .strokeStyle("#fff") - .fillStyle(function(l) { return l.linkValue ? "#555" : "#eee"; }) - .parent = this; - - /* No special add for links! */ - delete this.link.add; - - /* Labels are duplicated for top & left. */ - this.label - .data(function() { return labels; }) - .left(function() { return this.index & 1 ? dx * ((this.index >> 1) + .5) : 0; }) - .top(function() { return this.index & 1 ? 0 : dy * ((this.index >> 1) + .5); }) - .textMargin(4) - .textAlign(function() { return this.index & 1 ? "left" : "right"; }) - .textAngle(function() { return this.index & 1 ? -Math.PI / 2 : 0; }); - - /* The node mark is unused. */ - delete this.node; -}; - -pv.Layout.Matrix.prototype = pv.extend(pv.Layout.Network) - .property("directed", Boolean); - -/** - * Whether this matrix visualization is directed (bidirectional). By default, - * the graph is assumed to be undirected, such that the visualization is - * symmetric across the matrix diagonal. If the network is directed, then - * forward links are drawn above the diagonal, while reverse links are drawn - * below. - * - * @type boolean - * @name pv.Layout.Matrix.prototype.directed - */ - -/** - * Specifies an optional sort function. The sort function follows the same - * comparator contract required by {@link pv.Dom.Node#sort}. Specifying a sort - * function provides an alternative to sort the nodes as they are specified by - * the nodes property; the main advantage of doing this is that the - * comparator function can access implicit fields populated by the network - * layout, such as the linkDegree. - * - *

Note that matrix visualizations are particularly sensitive to order. This - * is referred to as the seriation problem, and many different techniques exist - * to find good node orders that emphasize clusters, such as spectral layout and - * simulated annealing. - * - * @param {function} f comparator function for nodes. - * @returns {pv.Layout.Matrix} this. - */ -pv.Layout.Matrix.prototype.sort = function(f) { - this.$sort = f; - return this; -}; - -/** @private */ -pv.Layout.Matrix.prototype.buildImplied = function(s) { - if (pv.Layout.Network.prototype.buildImplied.call(this, s)) return; - - var nodes = s.nodes, - links = s.links, - sort = this.$sort, - n = nodes.length, - index = pv.range(n), - labels = [], - pairs = [], - map = {}; - - s.$matrix = {labels: labels, pairs: pairs}; - - /* Sort the nodes. */ - if (sort) index.sort(function(a, b) { return sort(nodes[a], nodes[b]); }); - - /* Create pairs. */ - for (var i = 0; i < n; i++) { - for (var j = 0; j < n; j++) { - var a = index[i], - b = index[j], - p = { - row: i, - col: j, - sourceNode: nodes[a], - targetNode: nodes[b], - linkValue: 0 - }; - pairs.push(map[a + "." + b] = p); - } - } - - /* Create labels. */ - for (var i = 0; i < n; i++) { - var a = index[i]; - labels.push(nodes[a], nodes[a]); - } - - /* Accumulate link values. */ - for (var i = 0; i < links.length; i++) { - var l = links[i], - source = l.sourceNode.index, - target = l.targetNode.index, - value = l.linkValue; - map[source + "." + target].linkValue += value; - if (!s.directed) map[target + "." + source].linkValue += value; - } -}; -// ranges (bad, satisfactory, good) -// measures (actual, forecast) -// markers (previous, goal) - -/* - * Chart design based on the recommendations of Stephen Few. Implementation - * based on the work of Clint Ivy, Jamie Love, and Jason Davies. - * http://projects.instantcognition.com/protovis/bulletchart/ - */ - -/** - * Constructs a new, empty bullet layout. Layouts are not typically constructed - * directly; instead, they are added to an existing panel via - * {@link pv.Mark#add}. - * - * @class - * @extends pv.Layout - */ -pv.Layout.Bullet = function() { - pv.Layout.call(this); - var that = this, - buildImplied = that.buildImplied, - scale = that.x = pv.Scale.linear(), - orient, - horizontal, - rangeColor, - measureColor, - x; - - /** @private Cache layout state to optimize properties. */ - this.buildImplied = function(s) { - buildImplied.call(this, x = s); - orient = s.orient; - horizontal = /^left|right$/.test(orient); - rangeColor = pv.ramp("#bbb", "#eee") - .domain(0, Math.max(1, x.ranges.length - 1)); - measureColor = pv.ramp("steelblue", "lightsteelblue") - .domain(0, Math.max(1, x.measures.length - 1)); - }; - - /** - * The range prototype. - * - * @type pv.Mark - * @name pv.Layout.Bullet.prototype.range - */ - (this.range = new pv.Mark()) - .data(function() { return x.ranges; }) - .reverse(true) - .left(function() { return orient == "left" ? 0 : null; }) - .top(function() { return orient == "top" ? 0 : null; }) - .right(function() { return orient == "right" ? 0 : null; }) - .bottom(function() { return orient == "bottom" ? 0 : null; }) - .width(function(d) { return horizontal ? scale(d) : null; }) - .height(function(d) { return horizontal ? null : scale(d); }) - .fillStyle(function() { return rangeColor(this.index); }) - .antialias(false) - .parent = that; - - /** - * The measure prototype. - * - * @type pv.Mark - * @name pv.Layout.Bullet.prototype.measure - */ - (this.measure = new pv.Mark()) - .extend(this.range) - .data(function() { return x.measures; }) - .left(function() { return orient == "left" ? 0 : horizontal ? null : this.parent.width() / 3.25; }) - .top(function() { return orient == "top" ? 0 : horizontal ? this.parent.height() / 3.25 : null; }) - .right(function() { return orient == "right" ? 0 : horizontal ? null : this.parent.width() / 3.25; }) - .bottom(function() { return orient == "bottom" ? 0 : horizontal ? this.parent.height() / 3.25 : null; }) - .fillStyle(function() { return measureColor(this.index); }) - .parent = that; - - /** - * The marker prototype. - * - * @type pv.Mark - * @name pv.Layout.Bullet.prototype.marker - */ - (this.marker = new pv.Mark()) - .data(function() { return x.markers; }) - .left(function(d) { return orient == "left" ? scale(d) : horizontal ? null : this.parent.width() / 2; }) - .top(function(d) { return orient == "top" ? scale(d) : horizontal ? this.parent.height() / 2 : null; }) - .right(function(d) { return orient == "right" ? scale(d) : null; }) - .bottom(function(d) { return orient == "bottom" ? scale(d) : null; }) - .strokeStyle("black") - .shape("bar") - .shapeAngle(function() { return horizontal ? 0 : Math.PI / 2; }) - .parent = that; - - (this.tick = new pv.Mark()) - .data(function() { return scale.ticks(7); }) - .left(function(d) { return orient == "left" ? scale(d) : null; }) - .top(function(d) { return orient == "top" ? scale(d) : null; }) - .right(function(d) { return orient == "right" ? scale(d) : horizontal ? null : -6; }) - .bottom(function(d) { return orient == "bottom" ? scale(d) : horizontal ? -8 : null; }) - .height(function() { return horizontal ? 6 : null; }) - .width(function() { return horizontal ? null : 6; }) - .parent = that; -}; - -pv.Layout.Bullet.prototype = pv.extend(pv.Layout) - .property("orient", String) // left, right, top, bottom - .property("ranges") - .property("markers") - .property("measures") - .property("maximum", Number); - -/** - * Default properties for bullet layouts. - * - * @type pv.Layout.Bullet - */ -pv.Layout.Bullet.prototype.defaults = new pv.Layout.Bullet() - .extend(pv.Layout.prototype.defaults) - .orient("left") - .ranges([]) - .markers([]) - .measures([]); - -/** - * The orientation. - * - * @type string - * @name pv.Layout.Bullet.prototype.orient - */ - -/** - * The array of range values. - * - * @type array - * @name pv.Layout.Bullet.prototype.ranges - */ - -/** - * The array of marker values. - * - * @type array - * @name pv.Layout.Bullet.prototype.markers - */ - -/** - * The array of measure values. - * - * @type array - * @name pv.Layout.Bullet.prototype.measures - */ - -/** - * Optional; the maximum range value. - * - * @type number - * @name pv.Layout.Bullet.prototype.maximum - */ - -/** @private */ -pv.Layout.Bullet.prototype.buildImplied = function(s) { - pv.Layout.prototype.buildImplied.call(this, s); - var size = this.parent[/^left|right$/.test(s.orient) ? "width" : "height"](); - s.maximum = s.maximum || pv.max([].concat(s.ranges, s.markers, s.measures)); - this.x.domain(0, s.maximum).range(0, size); -}; -/** - * Abstract; see an implementing class for details. - * - * @class Represents a reusable interaction; applies an interactive behavior to - * a given mark. Behaviors are themselves functions designed to be used as event - * handlers. For example, to add pan and zoom support to any panel, say: - * - *

    .event("mousedown", pv.Behavior.pan())
- *     .event("mousewheel", pv.Behavior.zoom())
- * - * The behavior should be registered on the event that triggers the start of the - * behavior. Typically, the behavior will take care of registering for any - * additional events that are necessary. For example, dragging starts on - * mousedown, while the drag behavior automatically listens for mousemove and - * mouseup events on the window. By listening to the window, the behavior can - * continue to receive mouse events even if the mouse briefly leaves the mark - * being dragged, or even the root panel. - * - *

Each behavior implementation has specific requirements as to which events - * it supports, and how it should be used. For example, the drag behavior - * requires that the data associated with the mark be an object with x - * and y attributes, such as a {@link pv.Vector}, storing the mark's - * position. See an implementing class for details. - * - * @see pv.Behavior.drag - * @see pv.Behavior.pan - * @see pv.Behavior.point - * @see pv.Behavior.select - * @see pv.Behavior.zoom - * @extends function - */ -pv.Behavior = {}; -pv.Behavior.dragBase = function(shared){ - var events, // event registrations held during each selection - downElem, - cancelClick, - inited, - drag; - - shared.autoRender = true; - shared.positionConstraint = null; - shared.bound = function(v, a_p){ - return Math.max(drag.min[a_p], Math.min(drag.max[a_p], v)); - }; - - /** @private protovis mark event handler */ - function mousedown(d) { - // Initialize - if(!inited){ - inited = true; - this.addEventInterceptor('click', eventInterceptor, /*before*/true); - } - - // Add event handlers to follow the drag. - // These are unregistered on mouse up. - if(!events){ - var root = this.root.scene.$g; - events = [ - // Attaching events to the canvas (instead of only to the document) - // allows canceling the bubbling of the events before they - // reach the handlers of ascendant elements (of canvas). - [root, 'mousemove', pv.listen(root, 'mousemove', mousemove)], - [root, 'mouseup', pv.listen(root, 'mouseup', mouseup )], - - // It is still necessary to receive events - // that are sourced outside the canvas - [document, 'mousemove', pv.listen(document, 'mousemove', mousemove)], - [document, 'mouseup', pv.listen(document, 'mouseup', mouseup )] - ]; - } - - var ev = arguments[arguments.length - 1]; // last argument - downElem = ev.target; - cancelClick = false; - - // Prevent the event from bubbling off the canvas - // (if being handled by the root) - ev.stopPropagation(); - - // -------------- - - var m1 = this.mouse(); - var scene = this.scene; - var index = this.index; - - drag = - scene[index].drag = { - phase: 'start', - m: m1, // current relevant mouse position - m1: m1, // the mouse position of the mousedown - m2: null, // the mouse position of the current/last mousemove - d: d, // the datum in mousedown - scene: scene, // scene context - index: index // scene index - }; - - ev = wrapEvent(ev, drag); - - shared.dragstart.call(this, ev); - - var m = drag.m; - if(m !== m1){ - m1.x = m.x; - m1.y = m.y; - } - } - - /** @private DOM event handler */ - function mousemove(ev) { - if (!drag) { return; } - - drag.phase = 'move'; - - // Prevent the event from bubbling off the canvas - // (if being handled by the root) - ev.stopPropagation(); - - ev = wrapEvent(ev, drag); - - // In the context of the mousedown scene - var scene = drag.scene; - scene.mark.context(scene, drag.index, function() { - // this === scene.mark - var mprev = drag.m2 || drag.m1; - - var m2 = this.mouse(); - if(mprev && m2.distance2(mprev).dist2 <= 2){ - return; - } - - drag.m = drag.m2 = m2; - - shared.drag.call(this, ev); - - // m2 may have changed - var m = drag.m; - if(m !== m2){ - m2.x = m.x; - m2.y = m.y; - } - }); - } - - /** @private DOM event handler */ - function mouseup(ev) { - if (!drag) { return; } - - drag.phase = 'end'; - - var m2 = drag.m2; - - // A click event is generated whenever - // the element where the mouse goes down - // is the same element of where the mouse goes up. - // We will try to intercept the generated click event and swallow it, - // when some selection has occurred. - var isDrag = m2 && drag.m1.distance2(m2).dist2 > 0.1; - drag.canceled = !isDrag; - - cancelClick = isDrag && (downElem === ev.target); - if(!cancelClick){ - downElem = null; - } - - // Prevent the event from bubbling off the canvas - // (if being handled by the root) - ev.stopPropagation(); - - ev = wrapEvent(ev, drag); - - // Unregister events - if(events){ - events.forEach(function(registration){ - pv.unlisten.apply(pv, registration); - }); - events = null; - } - - var scene = drag.scene; - var index = drag.index; - try{ - scene.mark.context(scene, index, function() { - shared.dragend.call(this, ev); - }); - } finally { - drag = null; - delete scene[index].drag; - } - } - - function wrapEvent(ev, drag){ - try{ - ev.drag = drag; - return ev; - } catch(ex) { - // SWALLOW - } - - // wrap - var ev2 = {}; - for(var p in ev){ - var v = ev[p]; - ev2[p] = typeof v !== 'function' ? v : bindEventFun(f, ev); - } - - ev2._sourceEvent = ev; - - return ev2; - } - - function bindEventFun(f, ctx){ - return function(){ - return f.apply(ctx, arguments); - }; - } - - /** - * Intercepts click events and, - * if they were consequence - * of a mouse down and up of a selection, - * cancels them. - * - * @returns {boolean|array} - * false to indicate that the event is handled, - * otherwise, an event handler info array: [handler, type, scenes, index, ev]. - * - * @private - */ - function eventInterceptor(type, ev){ - if(cancelClick && downElem === ev.target){ - // Event is handled - cancelClick = false; - downElem = null; - return false; - } - - // Let event be handled normally - } - - - /** - * Whether to automatically render the mark when appropriate. - * - * @function - * @returns {pv.Behavior.dragBase | boolean} this, or the current autoRender parameter. - * @name pv.Behavior.dragBase.prototype.autoRender - * @param {string} [_] the new autoRender parameter - */ - mousedown.autoRender = function(_) { - if (arguments.length) { - shared.autoRender = !!_; - return mousedown; - } - - return shared.autoRender; - }; - - /** - * Gets or sets the positionConstraint parameter. - * - * A function that given a drag object - * can change its property m, - * containing a vector with the desired mouse position. - * - * @function - * @returns {pv.Behavior.dragBase | function} this, or the current positionConstraint parameter. - * @name pv.Behavior.dragBase.prototype.positionConstraint - * @param {function} [_] the new positionConstraint parameter - */ - mousedown.positionConstraint = function(_) { - if (arguments.length) { - shared.positionConstraint = _; - return mousedown; - } - - return shared.positionConstraint; - }; - - return mousedown; -}; - -/** - * Returns a new drag behavior to be registered on mousedown events. - * - * @class Implements interactive dragging starting with mousedown events. - * Register this behavior on marks that should be draggable by the user, such as - * the selected region for brushing and linking. This behavior can be used in - * tandom with {@link pv.Behavior.select} to allow the selected region to be - * dragged interactively. - * - *

After the initial mousedown event is triggered, this behavior listens for - * mousemove and mouseup events on the window. This allows dragging to continue - * even if the mouse temporarily leaves the mark that is being dragged, or even - * the root panel. - * - *

This behavior requires that the data associated with the mark being - * dragged have x and y attributes that correspond to the - * mark's location in pixels. The mark's positional properties are not set - * directly by this behavior; instead, the positional properties should be - * defined as: - * - *

    .left(function(d) d.x)
- *     .top(function(d) d.y)
- * - * Thus, the behavior does not move the mark directly, but instead updates the - * mark position by updating the underlying data. Note that if the positional - * properties are defined with bottom and right (rather than top and left), the - * drag behavior will be inverted, which will confuse users! - * - *

The drag behavior is bounded by the parent panel; the x and - * y attributes are clamped such that the mark being dragged does not - * extend outside the enclosing panel's bounds. To facilitate this, the drag - * behavior also queries for dx and dy attributes on the - * underlying data, to determine the dimensions of the bar being dragged. For - * non-rectangular marks, the drag behavior simply treats the mark as a point, - * which means that only the mark's center is bounded. - * - *

The mark being dragged is automatically re-rendered for each mouse event - * as part of the drag operation. In addition, a fix attribute is - * populated on the mark, which allows visual feedback for dragging. For - * example, to change the mark fill color while dragging: - * - *

    .fillStyle(function(d) d.fix ? "#ff7f0e" : "#aec7e8")
- * - * In some cases, such as with network layouts, dragging the mark may cause - * related marks to change, in which case additional marks may also need to be - * rendered. This can be accomplished by listening for the drag - * psuedo-events:
    - * - *
  • dragstart (on mousedown) - *
  • drag (on mousemove) - *
  • dragend (on mouseup) - * - *
For example, to render the parent panel while dragging, thus - * re-rendering all sibling marks: - * - *
    .event("mousedown", pv.Behavior.drag())
- *     .event("drag", function() this.parent)
- * - * This behavior may be enhanced in the future to allow more flexible - * configuration of drag behavior. - * - * @extends pv.Behavior - * @see pv.Behavior - * @see pv.Behavior.select - * @see pv.Layout.force - */ -pv.Behavior.drag = function() { - var collapse = null; // dimensions to collapse - var kx = 1; // x-dimension 1/0 - var ky = 1; // y-dimension 1/0 - - var v1; // initial mouse-particle offset - - // Executed in context of initial mark scene - var shared = { - dragstart: function(ev){ - var drag = ev.drag; - drag.type = 'drag'; - - var p = drag.d; // particle being dragged - var fix = pv.vector(p.x, p.y); - - p.fix = fix; - p.drag = drag; - - v1 = fix.minus(drag.m1); - - var parent = this.parent; - drag.max = { - x: parent.width() - (p.dx || 0), - y: parent.height() - (p.dy || 0) - }; - - drag.min = { - x: 0, - y: 0 - }; - - if(shared.autoRender){ - this.render(); - } - - pv.Mark.dispatch("dragstart", drag.scene, drag.index, ev); - }, - - drag: function(ev){ - var drag = ev.drag; - var m2 = drag.m2; - var p = drag.d; - - drag.m = v1.plus(m2); - - var constraint = shared.positionConstraint; - if(constraint){ - constraint(drag); - } - - var m = drag.m; - if(kx){ - p.x = p.fix.x = shared.bound(m.x, 'x'); - } - - if(ky){ - p.y = p.fix.y = shared.bound(m.y, 'y'); - } - - if(shared.autoRender){ - this.render(); - } - - pv.Mark.dispatch("drag", drag.scene, drag.index, ev); - }, - - dragend: function(ev){ - var drag = ev.drag; - var p = drag.d; - - p.fix = null; // pv compatibility - v1 = null; - - if(shared.autoRender){ - this.render(); - } - - try { - pv.Mark.dispatch('dragend', drag.scene, drag.index, ev); - } finally { - delete p.drag; - } - } - }; - - var mousedown = pv.Behavior.dragBase(shared); - - /** - * Sets or gets the collapse parameter. - * By default, dragging is sensitive to both dimensions. - * However, with some visualizations it is desirable to - * consider only a single dimension, such as the x-dimension for an - * independent variable. In this case, the collapse parameter can be set to - * collapse the y dimension: - * - *
    .event("mousedown", pv.Behavior.drag().collapse("y"))
- * - * @function - * @returns {pv.Behavior.drag} this, or the current collapse parameter. - * @name pv.Behavior.drag.prototype.collapse - * @param {string} [x] the new collapse parameter - */ - mousedown.collapse = function(x) { - if (arguments.length) { - collapse = String(x); - switch (collapse) { - case "y": kx = 1; ky = 0; break; - case "x": kx = 0; ky = 1; break; - default: kx = 1; ky = 1; break; - } - return mousedown; - } - return collapse; - }; - - return mousedown; -}; -/** - * Returns a new point behavior to be registered on mousemove events. - * - * @class Implements interactive fuzzy pointing, identifying marks that are in - * close proximity to the mouse cursor. This behavior is an alternative to the - * native mouseover and mouseout events, improving usability. Rather than - * requiring the user to mouseover a mark exactly, the mouse simply needs to - * move near the given mark and a "point" event is triggered. In addition, if - * multiple marks overlap, the point behavior can be used to identify the mark - * instance closest to the cursor, as opposed to the one that is rendered on - * top. - * - *

The point behavior can also identify the closest mark instance for marks - * that produce a continuous graphic primitive. The point behavior can thus be - * used to provide details-on-demand for both discrete marks (such as dots and - * bars), as well as continuous marks (such as lines and areas). - * - *

This behavior is implemented by finding the closest mark instance to the - * mouse cursor on every mousemove event. If this closest mark is within the - * given radius threshold, which defaults to 30 pixels, a "point" psuedo-event - * is dispatched to the given mark instance. If any mark were previously - * pointed, it would receive a corresponding "unpoint" event. These two - * psuedo-event types correspond to the native "mouseover" and "mouseout" - * events, respectively. To increase the radius at which the point behavior can - * be applied, specify an appropriate threshold to the constructor, up to - * Infinity. - * - *

By default, the standard Cartesian distance is computed. However, with - * some visualizations it is desirable to consider only a single dimension, such - * as the x-dimension for an independent variable. In this case, the - * collapse parameter can be set to collapse the y dimension: - * - *

    .event("mousemove", pv.Behavior.point(Infinity).collapse("y"))
- * - *

This behavior only listens to mousemove events on the assigned panel, - * which is typically the root panel. The behavior will search recursively for - * descendant marks to point. If the mouse leaves the assigned panel, the - * behavior no longer receives mousemove events; an unpoint psuedo-event is - * automatically dispatched to unpoint any pointed mark. Marks may be re-pointed - * when the mouse reenters the panel. - * - *

Panels have transparent fill styles by default; this means that panels may - * not receive the initial mousemove event to start pointing. To fix this - * problem, either given the panel a visible fill style (such as "white"), or - * set the events property to "all" such that the panel receives events - * despite its transparent fill. - * - *

Note: this behavior does not currently wedge marks. - * - * @extends pv.Behavior - * - * @param {number} [r] the fuzzy radius threshold in pixels - * @see "The Bubble Cursor: Enhancing Target Acquisition by Dynamic Resizing of the - * Cursor's Activation Area" by T. Grossman & R. Balakrishnan, CHI 2005. - */ -pv.Behavior.point = function(r) { - var unpoint, // the current pointer target - collapse = null, // dimensions to collapse - kx = 1, // x-dimension cost scale - ky = 1, // y-dimension cost scale - pointingPanel = null, - r2 = arguments.length ? r * r : 900; // fuzzy radius - - /** @private Search for the mark closest to the mouse. */ - function search(scene, index) { - var s = scene[index], - point = {cost: Infinity}; - for (var i = (s.visible ? s.children.length : 0) - 1 ; i >= 0; i--) { - var child = s.children[i], mark = child.mark, p; - if (mark.type == "panel") { - mark.scene = child; - for (var j = child.length - 1 ; j >= 0; j--) { - mark.index = j; - p = search(child, j); - if (p.cost < point.cost) point = p; - } - delete mark.scene; - delete mark.index; - } else if (mark.$handlers.point) { - var v = mark.mouse(); - for (var j = child.length - 1 ; j >= 0; j--) { - var c = child[j], - dx = v.x - c.left - (c.width || 0) / 2, - dy = v.y - c.top - (c.height || 0) / 2, - dd = kx * dx * dx + ky * dy * dy; - if (dd < point.cost) { - point.distance = dx * dx + dy * dy; - point.cost = dd; - point.scene = child; - point.index = j; - } - } - } - } - return point; - } - - /** @private */ - function mousemove(e) { - /* If the closest mark is far away, clear the current target. */ - var point = search(this.scene, this.index); - if ((point.cost == Infinity) || (point.distance > r2)) point = null; - - /* Unpoint the old target, if it's not the new target. */ - if (unpoint) { - if (point - && (unpoint.scene == point.scene) - && (unpoint.index == point.index)) return; - pv.Mark.dispatch("unpoint", unpoint.scene, unpoint.index, e); - } - - /* Point the new target, if there is one. */ - if (unpoint = point) { - pv.Mark.dispatch("point", point.scene, point.index, e); - - /* Unpoint when the mouse leaves the pointing panel. */ - if(!pointingPanel && this.type === 'panel') { - pointingPanel = this; - pointingPanel.event('mouseout', function(){ - var ev = arguments[arguments.length - 1]; - mouseout.call(pointingPanel.scene.$g, ev); - }); - } else { - pv.listen(this.root.canvas(), "mouseout", mouseout); - } - } - } - - /** @private */ - function mouseout(e) { - if (unpoint && !pv.ancestor(this, e.relatedTarget)) { - pv.Mark.dispatch("unpoint", unpoint.scene, unpoint.index, e); - unpoint = null; - } - } - - /** - * Sets or gets the collapse parameter. By default, the standard Cartesian - * distance is computed. However, with some visualizations it is desirable to - * consider only a single dimension, such as the x-dimension for an - * independent variable. In this case, the collapse parameter can be set to - * collapse the y dimension: - * - *

    .event("mousemove", pv.Behavior.point(Infinity).collapse("y"))
- * - * @function - * @returns {pv.Behavior.point} this, or the current collapse parameter. - * @name pv.Behavior.point.prototype.collapse - * @param {string} [x] the new collapse parameter - */ - mousemove.collapse = function(x) { - if (arguments.length) { - collapse = String(x); - switch (collapse) { - case "y": kx = 1; ky = 0; break; - case "x": kx = 0; ky = 1; break; - default: kx = 1; ky = 1; break; - } - return mousemove; - } - return collapse; - }; - - return mousemove; -};/** - * Returns a new select behavior to be registered on mousedown events. - * - * @class Implements interactive selecting starting with mousedown events. - * Register this behavior on panels that should be selectable by the user, such - * for brushing and linking. This behavior can be used in tandom with - * {@link pv.Behavior.drag} to allow the selected region to be dragged - * interactively. - * - *

After the initial mousedown event is triggered, this behavior listens for - * mousemove and mouseup events on the window. This allows selecting to continue - * even if the mouse temporarily leaves the assigned panel, or even the root - * panel. - * - *

This behavior requires that the data associated with the mark being - * dragged have x, y, dx and dy attributes - * that correspond to the mark's location and dimensions in pixels. The mark's - * positional properties are not set directly by this behavior; instead, the - * positional properties should be defined as: - * - *

    .left(function(d) d.x)
- *     .top(function(d) d.y)
- *     .width(function(d) d.dx)
- *     .height(function(d) d.dy)
- * - * Thus, the behavior does not resize the mark directly, but instead updates the - * selection by updating the assigned panel's underlying data. Note that if the - * positional properties are defined with bottom and right (rather than top and - * left), the drag behavior will be inverted, which will confuse users! - * - *

The select behavior is bounded by the assigned panel; the positional - * attributes are clamped such that the selection does not extend outside the - * panel's bounds. - * - *

The panel being selected is automatically re-rendered for each mouse event - * as part of the drag operation. This behavior may be enhanced in the future to - * allow more flexible configuration of select behavior. In some cases, such as - * with parallel coordinates, making a selection may cause related marks to - * change, in which case additional marks may also need to be rendered. This can - * be accomplished by listening for the select pseudo-events:

    - * - *
  • selectstart (on mousedown) - *
  • select (on mousemove) - *
  • selectend (on mouseup) - * - *
For example, to render the parent panel while selecting, thus - * re-rendering all sibling marks: - * - *
    .event("mousedown", pv.Behavior.drag())
- *     .event("select", function() this.parent)
- * - * This behavior may be enhanced in the future to allow more flexible - * configuration of the selection behavior. - * - * @extends pv.Behavior - * @see pv.Behavior.drag - */ -pv.Behavior.select = function(){ - var collapse = null; // dimensions to collapse - var kx = 1; // x-dimension 1/0 - var ky = 1; // y-dimension 1/0 - var preserveLength = false; - - // Executed in context of initial mark scene - var shared = { - dragstart: function(ev){ - var drag = ev.drag; - drag.type = 'select'; - - var r = drag.d; - r.drag = drag; - - drag.max = { - x: this.width(), - y: this.height() - }; - - drag.min = { - x: 0, - y: 0 - }; - - var constraint = shared.positionConstraint; - if(constraint){ - drag.m = drag.m.clone(); - constraint(drag); - } - - var m = drag.m; - if(kx){ - r.x = shared.bound(m.x, 'x'); - if(!preserveLength){ - r.dx = 0; - } - } - - if(ky){ - r.y = shared.bound(m.y, 'y'); - if(!preserveLength){ - r.dy = 0; - } - } - - pv.Mark.dispatch('selectstart', drag.scene, drag.index, ev); - }, - - drag: function(ev){ - var drag = ev.drag; - var m1 = drag.m1; - var r = drag.d; - - drag.max.x = this.width(); - drag.max.y = this.height(); - - var constraint = shared.positionConstraint; - if(constraint){ - drag.m = drag.m.clone(); - constraint(drag); - } - - var m = drag.m; - - if(kx){ - var bx = Math.min(m1.x, m.x); - bx = shared.bound(bx, 'x'); - r.x = bx; - - if(!preserveLength){ - var ex = Math.max(m.x, m1.x); - ex = shared.bound(ex, 'x'); - r.dx = ex - bx; - } - } - - if(ky){ - var by = Math.min(m1.y, m.y); - by = shared.bound(by, 'y'); - r.y = by; - - if(!preserveLength){ - var ey = Math.max(m.y, m1.y); - ey = shared.bound(ey, 'y'); - r.dy = ey - by; - } - } - - if(shared.autoRender){ - this.render(); - } - - pv.Mark.dispatch('select', drag.scene, drag.index, ev); - }, - - dragend: function(ev){ - var drag = ev.drag; - try { - pv.Mark.dispatch('selectend', drag.scene, drag.index, ev); - } finally { - var r = drag.d; - delete r.drag; - } - } - }; - - var mousedown = pv.Behavior.dragBase(shared); - - /** - * Sets or gets the collapse parameter. - * By default, the selection rectangle is sensitive to both dimensions. - * However, with some visualizations it is desirable to - * consider only a single dimension, such as the x-dimension for an - * independent variable. In this case, the collapse parameter can be set to - * collapse the y dimension: - * - *
    .event("mousedown", pv.Behavior.select().collapse("y"))
- * - * @function - * @returns {pv.Behavior.select} this, or the current collapse parameter. - * @name pv.Behavior.select.prototype.collapse - * @param {string} [x] the new collapse parameter - */ - mousedown.collapse = function(x) { - if (arguments.length) { - collapse = String(x); - switch (collapse) { - case "y": kx = 1; ky = 0; break; - case "x": kx = 0; ky = 1; break; - default: kx = 1; ky = 1; break; - } - return mousedown; - } - return collapse; - }; - - mousedown.preserveLength = function(_) { - if (arguments.length) { - preserveLength = !!_; - return mousedown; - } - return preserveLength; - }; - - return mousedown; -}; -/** - * Returns a new resize behavior to be registered on mousedown events. - * - * @class Implements interactive resizing of a selection starting with mousedown - * events. Register this behavior on selection handles that should be resizeable - * by the user, such for brushing and linking. This behavior can be used in - * tandom with {@link pv.Behavior.select} and {@link pv.Behavior.drag} to allow - * the selected region to be selected and dragged interactively. - * - *

After the initial mousedown event is triggered, this behavior listens for - * mousemove and mouseup events on the window. This allows resizing to continue - * even if the mouse temporarily leaves the assigned panel, or even the root - * panel. - * - *

This behavior requires that the data associated with the mark being - * resized have x, y, dx and dy attributes - * that correspond to the mark's location and dimensions in pixels. The mark's - * positional properties are not set directly by this behavior; instead, the - * positional properties should be defined as: - * - *

    .left(function(d) d.x)
- *     .top(function(d) d.y)
- *     .width(function(d) d.dx)
- *     .height(function(d) d.dy)
- * - * Thus, the behavior does not resize the mark directly, but instead updates the - * size by updating the assigned panel's underlying data. Note that if the - * positional properties are defined with bottom and right (rather than top and - * left), the resize behavior will be inverted, which will confuse users! - * - *

The resize behavior is bounded by the assigned mark's enclosing panel; the - * positional attributes are clamped such that the selection does not extend - * outside the panel's bounds. - * - *

The mark being resized is automatically re-rendered for each mouse event - * as part of the resize operation. This behavior may be enhanced in the future - * to allow more flexible configuration. In some cases, such as with parallel - * coordinates, resizing the selection may cause related marks to change, in - * which case additional marks may also need to be rendered. This can be - * accomplished by listening for the select psuedo-events:

    - * - *
  • resizestart (on mousedown) - *
  • resize (on mousemove) - *
  • resizeend (on mouseup) - * - *
For example, to render the parent panel while resizing, thus - * re-rendering all sibling marks: - * - *
    .event("mousedown", pv.Behavior.resize("left"))
- *     .event("resize", function() this.parent)
- * - * This behavior may be enhanced in the future to allow more flexible - * configuration of the selection behavior. - * - * @extends pv.Behavior - * @see pv.Behavior.select - * @see pv.Behavior.drag - */ -pv.Behavior.resize = function(side) { - var preserveOrtho = false; - - var isLeftRight = (side === 'left' || side === 'right'); - - // Executed in context of initial mark scene - var shared = { - dragstart: function(ev){ - var drag = ev.drag; - drag.type = 'resize'; - - var m1 = drag.m1; - var r = drag.d; - r.drag = drag; - - // Fix the position of m1 to be the opposite side, - // the one whose position is fixed during resizing - switch(side) { - case "left": m1.x = r.x + r.dx; break; - case "right": m1.x = r.x; break; - case "top": m1.y = r.y + r.dy; break; - case "bottom": m1.y = r.y; break; - } - - // Capture parent's dimensions once - // These can be overridden to change the bounds checking behavior - var parent = this.parent; - drag.max = { - x: parent.width(), - y: parent.height() - }; - - drag.min = { - x: 0, - y: 0 - }; - - pv.Mark.dispatch("resizestart", drag.scene, drag.index, ev); - }, - - drag: function(ev){ - var drag = ev.drag; - - var m1 = drag.m1; - var constraint = shared.positionConstraint; - if(constraint){ - drag.m = drag.m.clone(); - constraint(drag); - } - - var m = drag.m; - var r = drag.d; - - if(!preserveOrtho || isLeftRight){ - var bx = Math.min(m1.x, m.x ); - var ex = Math.max(m.x, m1.x); - - bx = shared.bound(bx, 'x'); - ex = shared.bound(ex, 'x'); - - r.x = bx; - r.dx = ex - bx; - } - - if(!preserveOrtho || !isLeftRight){ - var by = Math.min(m1.y, m.y ); - var ey = Math.max(m.y, m1.y); - - bx = shared.bound(by, 'y'); - ex = shared.bound(ey, 'y'); - - r.y = by; - r.dy = ey - by; - } - - if(shared.autoRender){ - this.render(); - } - - pv.Mark.dispatch("resize", drag.scene, drag.index, ev); - }, - - dragend: function(ev){ - var drag = ev.drag; - - max = null; - try { - pv.Mark.dispatch('resizeend', drag.scene, drag.index, ev); - } finally { - var r = drag.d; - delete r.drag; - } - } - }; - - var mousedown = pv.Behavior.dragBase(shared); - - /** - * Sets or gets the preserveOrtho. - * - * When true - * doesn't update coordinates orthogonal to the behaviou's side. - * The default value is false. - * - * @function - * @returns {pv.Behavior.resize | boolean} this, or the current preserveOrtho parameter. - * @name pv.Behavior.resize.prototype.preserveOrtho - * @param {boolean} [_] the new preserveOrtho parameter - */ - mousedown.preserveOrtho = function(_) { - if (arguments.length){ - preserveOrtho = !!_; - return mousedown; - } - return preserveOrtho; - }; - - return mousedown; -}; -/** - * Returns a new pan behavior to be registered on mousedown events. - * - * @class Implements interactive panning starting with mousedown events. - * Register this behavior on panels to allow panning. This behavior can be used - * in tandem with {@link pv.Behavior.zoom} to allow both panning and zooming: - * - *
    .event("mousedown", pv.Behavior.pan())
- *     .event("mousewheel", pv.Behavior.zoom())
- * - * The pan behavior currently supports only mouse events; support for keyboard - * shortcuts to improve accessibility may be added in the future. - * - *

After the initial mousedown event is triggered, this behavior listens for - * mousemove and mouseup events on the window. This allows panning to continue - * even if the mouse temporarily leaves the panel that is being panned, or even - * the root panel. - * - *

The implementation of this behavior relies on the panel's - * transform property, which specifies a matrix transformation that is - * applied to child marks. Note that the transform property only affects the - * panel's children, but not the panel itself; therefore the panel's fill and - * stroke will not change when the contents are panned. - * - *

Panels have transparent fill styles by default; this means that panels may - * not receive the initial mousedown event to start panning. To fix this - * problem, either given the panel a visible fill style (such as "white"), or - * set the events property to "all" such that the panel receives events - * despite its transparent fill. - * - *

The pan behavior has optional support for bounding. If enabled, the user - * will not be able to pan the panel outside of the initial bounds. This feature - * is designed to work in conjunction with the zoom behavior; otherwise, - * bounding the panel effectively disables all panning. - * - * @extends pv.Behavior - * @see pv.Behavior.zoom - * @see pv.Panel#transform - */ -pv.Behavior.pan = function() { - var scene, // scene context - index, // scene context - m1, // transformation matrix at the start of panning - v1, // mouse location at the start of panning - k, // inverse scale - bound; // whether to bound to the panel - - /** @private */ - function mousedown() { - index = this.index; - scene = this.scene; - v1 = pv.vector(pv.event.pageX, pv.event.pageY); - m1 = this.transform(); - k = 1 / (m1.k * this.scale); - if (bound) { - bound = { - x: (1 - m1.k) * this.width(), - y: (1 - m1.k) * this.height() - }; - } - } - - /** @private */ - function mousemove(e) { - if (!scene) return; - scene.mark.context(scene, index, function() { - var x = (pv.event.pageX - v1.x) * k, - y = (pv.event.pageY - v1.y) * k, - m = m1.translate(x, y); - if (bound) { - m.x = Math.max(bound.x, Math.min(0, m.x)); - m.y = Math.max(bound.y, Math.min(0, m.y)); - } - this.transform(m).render(); - }); - pv.Mark.dispatch("pan", scene, index, e); - } - - /** @private */ - function mouseup() { - scene = null; - } - - /** - * Sets or gets the bound parameter. If bounding is enabled, the user will not - * be able to pan outside the initial panel bounds; this typically applies - * only when the pan behavior is used in tandem with the zoom behavior. - * Bounding is not enabled by default. - * - *

Note: enabling bounding after panning has already occurred will not - * immediately reset the transform. Bounding should be enabled before the - * panning behavior is applied. - * - * @function - * @returns {pv.Behavior.pan} this, or the current bound parameter. - * @name pv.Behavior.pan.prototype.bound - * @param {boolean} [x] the new bound parameter. - */ - mousedown.bound = function(x) { - if (arguments.length) { - bound = Boolean(x); - return this; - } - return Boolean(bound); - }; - - pv.listen(window, "mousemove", mousemove); - pv.listen(window, "mouseup", mouseup); - return mousedown; -}; -/** - * Returns a new zoom behavior to be registered on mousewheel events. - * - * @class Implements interactive zooming using mousewheel events. Register this - * behavior on panels to allow zooming. This behavior can be used in tandem with - * {@link pv.Behavior.pan} to allow both panning and zooming: - * - *

    .event("mousedown", pv.Behavior.pan())
- *     .event("mousewheel", pv.Behavior.zoom())
- * - * The zoom behavior currently supports only mousewheel events; support for - * keyboard shortcuts and gesture events to improve accessibility may be added - * in the future. - * - *

The implementation of this behavior relies on the panel's - * transform property, which specifies a matrix transformation that is - * applied to child marks. Note that the transform property only affects the - * panel's children, but not the panel itself; therefore the panel's fill and - * stroke will not change when the contents are zoomed. The built-in support for - * transforms only supports uniform scaling and translates, which is sufficient - * for panning and zooming. Note that this is not a strict geometric - * transformation, as the lineWidth property is scale-aware: strokes - * are drawn at constant size independent of scale. - * - *

Panels have transparent fill styles by default; this means that panels may - * not receive mousewheel events to zoom. To fix this problem, either given the - * panel a visible fill style (such as "white"), or set the events - * property to "all" such that the panel receives events despite its transparent - * fill. - * - *

The zoom behavior has optional support for bounding. If enabled, the user - * will not be able to zoom out farther than the initial bounds. This feature is - * designed to work in conjunction with the pan behavior. - * - * @extends pv.Behavior - * @see pv.Panel#transform - * @see pv.Mark#scale - * @param {number} speed - */ -pv.Behavior.zoom = function(speed) { - var bound; // whether to bound to the panel - - if (!arguments.length) speed = 1 / 48; - - /** @private */ - function mousewheel(e) { - var v = this.mouse(), - k = pv.event.wheel * speed, - m = this.transform().translate(v.x, v.y) - .scale((k < 0) ? (1e3 / (1e3 - k)) : ((1e3 + k) / 1e3)) - .translate(-v.x, -v.y); - if (bound) { - m.k = Math.max(1, m.k); - m.x = Math.max((1 - m.k) * this.width(), Math.min(0, m.x)); - m.y = Math.max((1 - m.k) * this.height(), Math.min(0, m.y)); - } - this.transform(m).render(); - pv.Mark.dispatch("zoom", this.scene, this.index, e); - } - - /** - * Sets or gets the bound parameter. If bounding is enabled, the user will not - * be able to zoom out farther than the initial panel bounds. Bounding is not - * enabled by default. If this behavior is used in tandem with the pan - * behavior, both should use the same bound parameter. - * - *

Note: enabling bounding after zooming has already occurred will not - * immediately reset the transform. Bounding should be enabled before the zoom - * behavior is applied. - * - * @function - * @returns {pv.Behavior.zoom} this, or the current bound parameter. - * @name pv.Behavior.zoom.prototype.bound - * @param {boolean} [x] the new bound parameter. - */ - mousewheel.bound = function(x) { - if (arguments.length) { - bound = Boolean(x); - return this; - } - return Boolean(bound); - }; - - return mousewheel; -}; -/** - * @ignore - * @namespace - */ -pv.Geo = function() {}; -/** - * Abstract; not implemented. There is no explicit constructor; this class - * merely serves to document the representation used by {@link pv.Geo.scale}. - * - * @class Represents a pair of geographic coordinates. - * - * @name pv.Geo.LatLng - * @see pv.Geo.scale - */ - -/** - * The latitude coordinate in degrees; positive is North. - * - * @type number - * @name pv.Geo.LatLng.prototype.lat - */ - -/** - * The longitude coordinate in degrees; positive is East. - * - * @type number - * @name pv.Geo.LatLng.prototype.lng - */ -/** - * Abstract; not implemented. There is no explicit constructor; this class - * merely serves to document the representation used by {@link pv.Geo.scale}. - * - * @class Represents a geographic projection. This class provides the core - * implementation for {@link pv.Geo.scale}s, mapping between geographic - * coordinates (latitude and longitude) and normalized screen space in the range - * [-1,1]. The remaining mapping between normalized screen space and actual - * pixels is performed by pv.Geo.scale. - * - *

Many geographic projections have a point around which the projection is - * centered. Rather than have each implementation add support for a - * user-specified center point, the pv.Geo.scale translates the - * geographic coordinates relative to the center point for both the forward and - * inverse projection. - * - *

In general, this class should not be used directly, unless the desire is - * to implement a new geographic projection. Instead, use pv.Geo.scale. - * Implementations are not required to implement inverse projections, but are - * needed for some forms of interactivity. Also note that some inverse - * projections are ambiguous, such as the connecting points in Dymaxian maps. - * - * @name pv.Geo.Projection - * @see pv.Geo.scale - */ - -/** - * The forward projection. - * - * @function - * @name pv.Geo.Projection.prototype.project - * @param {pv.Geo.LatLng} latlng the latitude and longitude to project. - * @returns {pv.Vector} the xy-coordinates of the given point. - */ - -/** - * The inverse projection; optional. - * - * @function - * @name pv.Geo.Projection.prototype.invert - * @param {pv.Vector} xy the x- and y-coordinates to invert. - * @returns {pv.Geo.LatLng} the latitude and longitude of the given point. - */ -/** - * The built-in projections. - * - * @see pv.Geo.Projection - * @namespace - */ -pv.Geo.projections = { - - /** @see http://en.wikipedia.org/wiki/Mercator_projection */ - mercator: { - project: function(latlng) { - return { - x: latlng.lng / 180, - y: latlng.lat > 85 ? 1 : latlng.lat < -85 ? -1 - : Math.log(Math.tan(Math.PI / 4 - + pv.radians(latlng.lat) / 2)) / Math.PI - }; - }, - invert: function(xy) { - return { - lng: xy.x * 180, - lat: pv.degrees(2 * Math.atan(Math.exp(xy.y * Math.PI)) - Math.PI / 2) - }; - } - }, - - /** @see http://en.wikipedia.org/wiki/Gall-Peters_projection */ - "gall-peters": { - project: function(latlng) { - return { - x: latlng.lng / 180, - y: Math.sin(pv.radians(latlng.lat)) - }; - }, - invert: function(xy) { - return { - lng: xy.x * 180, - lat: pv.degrees(Math.asin(xy.y)) - }; - } - }, - - /** @see http://en.wikipedia.org/wiki/Sinusoidal_projection */ - sinusoidal: { - project: function(latlng) { - return { - x: pv.radians(latlng.lng) * Math.cos(pv.radians(latlng.lat)) / Math.PI, - y: latlng.lat / 90 - }; - }, - invert: function(xy) { - return { - lng: pv.degrees((xy.x * Math.PI) / Math.cos(xy.y * Math.PI / 2)), - lat: xy.y * 90 - }; - } - }, - - /** @see http://en.wikipedia.org/wiki/Aitoff_projection */ - aitoff: { - project: function(latlng) { - var l = pv.radians(latlng.lng), - f = pv.radians(latlng.lat), - a = Math.acos(Math.cos(f) * Math.cos(l / 2)); - return { - x: 2 * (a ? (Math.cos(f) * Math.sin(l / 2) * a / Math.sin(a)) : 0) / Math.PI, - y: 2 * (a ? (Math.sin(f) * a / Math.sin(a)) : 0) / Math.PI - }; - }, - invert: function(xy) { - var x = xy.x * Math.PI / 2, - y = xy.y * Math.PI / 2; - return { - lng: pv.degrees(x / Math.cos(y)), - lat: pv.degrees(y) - }; - } - }, - - /** @see http://en.wikipedia.org/wiki/Hammer_projection */ - hammer: { - project: function(latlng) { - var l = pv.radians(latlng.lng), - f = pv.radians(latlng.lat), - c = Math.sqrt(1 + Math.cos(f) * Math.cos(l / 2)); - return { - x: 2 * Math.SQRT2 * Math.cos(f) * Math.sin(l / 2) / c / 3, - y: Math.SQRT2 * Math.sin(f) / c / 1.5 - }; - }, - invert: function(xy) { - var x = xy.x * 3, - y = xy.y * 1.5, - z = Math.sqrt(1 - x * x / 16 - y * y / 4); - return { - lng: pv.degrees(2 * Math.atan2(z * x, 2 * (2 * z * z - 1))), - lat: pv.degrees(Math.asin(z * y)) - }; - } - }, - - /** The identity or "none" projection. */ - identity: { - project: function(latlng) { - return { - x: latlng.lng / 180, - y: latlng.lat / 90 - }; - }, - invert: function(xy) { - return { - lng: xy.x * 180, - lat: xy.y * 90 - }; - } - } -}; -/** - * Returns a geographic scale. The arguments to this constructor are optional, - * and equivalent to calling {@link #projection}. - * - * @class Represents a geographic scale; a mapping between latitude-longitude - * coordinates and screen pixel coordinates. By default, the domain is inferred - * from the geographic coordinates, so that the domain fills the output range. - * - *

Note that geographic scales are two-dimensional transformations, rather - * than the one-dimensional bidrectional mapping typical of other scales. - * Rather than mapping (for example) between a numeric domain and a numeric - * range, geographic scales map between two coordinate objects: {@link - * pv.Geo.LatLng} and {@link pv.Vector}. - * - * @param {pv.Geo.Projection} [p] optional projection. - * @see pv.Geo.scale#ticks - */ -pv.Geo.scale = function(p) { - var rmin = {x: 0, y: 0}, // default range minimum - rmax = {x: 1, y: 1}, // default range maximum - d = [], // default domain - j = pv.Geo.projections.identity, // domain <-> normalized range - x = pv.Scale.linear(-1, 1).range(0, 1), // normalized <-> range - y = pv.Scale.linear(-1, 1).range(1, 0), // normalized <-> range - c = {lng: 0, lat: 0}, // Center Point - lastLatLng, // cached latlng - lastPoint; // cached point - - /** @private */ - function scale(latlng) { - if (!lastLatLng - || (latlng.lng != lastLatLng.lng) - || (latlng.lat != lastLatLng.lat)) { - lastLatLng = latlng; - var p = project(latlng); - lastPoint = {x: x(p.x), y: y(p.y)}; - } - return lastPoint; - } - - /** @private */ - function project(latlng) { - var offset = {lng: latlng.lng - c.lng, lat: latlng.lat}; - return j.project(offset); - } - - /** @private */ - function invert(xy) { - var latlng = j.invert(xy); - latlng.lng += c.lng; - return latlng; - } - - /** Returns the projected x-coordinate. */ - scale.x = function(latlng) { - return scale(latlng).x; - }; - - /** Returns the projected y-coordinate. */ - scale.y = function(latlng) { - return scale(latlng).y; - }; - - /** - * Abstract; this is a local namespace on a given geographic scale. - * - * @namespace Tick functions for geographic scales. Because geographic scales - * represent two-dimensional transformations (as opposed to one-dimensional - * transformations typical of other scales), the tick values are similarly - * represented as two-dimensional coordinates in the input domain, i.e., - * {@link pv.Geo.LatLng} objects. - * - *

Also, note that non-rectilinear projections, such as sinsuoidal and - * aitoff, may not produce straight lines for constant longitude or constant - * latitude. Therefore the returned array of ticks is a two-dimensional array, - * sampling various latitudes as constant longitude, and vice versa. - * - *

The tick lines can therefore be approximated as polylines, either with - * "linear" or "cardinal" interpolation. This is not as accurate as drawing - * the true curve through the projection space, but is usually sufficient. - * - * @name pv.Geo.scale.prototype.ticks - * @see pv.Geo.scale - * @see pv.Geo.LatLng - * @see pv.Line#interpolate - */ - scale.ticks = { - - /** - * Returns longitude ticks. - * - * @function - * @param {number} [m] the desired number of ticks. - * @returns {array} a nested array of pv.Geo.LatLng ticks. - * @name pv.Geo.scale.prototype.ticks.prototype.lng - */ - lng: function(m) { - var lat, lng; - if (d.length > 1) { - var s = pv.Scale.linear(); - if (m == undefined) m = 10; - lat = s.domain(d, function(d) { return d.lat; }).ticks(m); - lng = s.domain(d, function(d) { return d.lng; }).ticks(m); - } else { - lat = pv.range(-80, 81, 10); - lng = pv.range(-180, 181, 10); - } - return lng.map(function(lng) { - return lat.map(function(lat) { - return {lat: lat, lng: lng}; - }); - }); - }, - - /** - * Returns latitude ticks. - * - * @function - * @param {number} [m] the desired number of ticks. - * @returns {array} a nested array of pv.Geo.LatLng ticks. - * @name pv.Geo.scale.prototype.ticks.prototype.lat - */ - lat: function(m) { - return pv.transpose(scale.ticks.lng(m)); - } - }; - - /** - * Inverts the specified value in the output range, returning the - * corresponding value in the input domain. This is frequently used to convert - * the mouse location (see {@link pv.Mark#mouse}) to a value in the input - * domain. Inversion is only supported for numeric ranges, and not colors. - * - *

Note that this method does not do any rounding or bounds checking. If - * the input domain is discrete (e.g., an array index), the returned value - * should be rounded. If the specified y value is outside the range, - * the returned value may be equivalently outside the input domain. - * - * @function - * @name pv.Geo.scale.prototype.invert - * @param {number} y a value in the output range (a pixel location). - * @returns {number} a value in the input domain. - */ - scale.invert = function(p) { - return invert({x: x.invert(p.x), y: y.invert(p.y)}); - }; - - /** - * Sets or gets the input domain. Note that unlike quantitative scales, the - * domain cannot be reduced to a simple rectangle (i.e., minimum and maximum - * values for latitude and longitude). Instead, the domain values must be - * projected to normalized space, effectively finding the domain in normalized - * space rather than in terms of latitude and longitude. Thus, changing the - * projection requires recomputing the normalized domain. - * - *

This method can be invoked several ways: - * - *

1. domain(values...) - * - *

Specifying the domain as a series of {@link pv.Geo.LatLng}s is the most - * explicit and recommended approach. However, if the domain values are - * derived from data, you may find the second method more appropriate. - * - *

2. domain(array, f) - * - *

Rather than enumerating the domain explicitly, you can specify a single - * argument of an array. In addition, you can specify an optional accessor - * function to extract the domain values (as {@link pv.Geo.LatLng}s) from the - * array. If the specified array has fewer than two elements, this scale will - * default to the full normalized domain. - * - *

2. domain() - * - *

Invoking the domain method with no arguments returns the - * current domain as an array. - * - * @function - * @name pv.Geo.scale.prototype.domain - * @param {...} domain... domain values. - * @returns {pv.Geo.scale} this, or the current domain. - */ - scale.domain = function(array, f) { - if (arguments.length) { - d = (array instanceof Array) - ? ((arguments.length > 1) ? pv.map(array, f) : array) - : Array.prototype.slice.call(arguments); - if (d.length > 1) { - var lngs = d.map(function(c) { return c.lng; }); - var lats = d.map(function(c) { return c.lat; }); - c = { - lng: (pv.max(lngs) + pv.min(lngs)) / 2, - lat: (pv.max(lats) + pv.min(lats)) / 2 - }; - var n = d.map(project); // normalized domain - x.domain(n, function(p) { return p.x; }); - y.domain(n, function(p) { return p.y; }); - } else { - c = {lng: 0, lat: 0}; - x.domain(-1, 1); - y.domain(-1, 1); - } - lastLatLng = null; // invalidate the cache - return this; - } - return d; - }; - - /** - * Sets or gets the output range. This method can be invoked several ways: - * - *

1. range(min, max) - * - *

If two objects are specified, the arguments should be {@link pv.Vector}s - * which specify the minimum and maximum values of the x- and y-coordinates - * explicitly. - * - *

2. range(width, height) - * - *

If two numbers are specified, the arguments specify the maximum values - * of the x- and y-coordinates explicitly; the minimum values are implicitly - * zero. - * - *

3. range() - * - *

Invoking the range method with no arguments returns the current - * range as an array of two {@link pv.Vector}s: the minimum (top-left) and - * maximum (bottom-right) values. - * - * @function - * @name pv.Geo.scale.prototype.range - * @param {...} range... range values. - * @returns {pv.Geo.scale} this, or the current range. - */ - scale.range = function(min, max) { - if (arguments.length) { - if (typeof min == "object") { - rmin = {x: Number(min.x), y: Number(min.y)}; - rmax = {x: Number(max.x), y: Number(max.y)}; - } else { - rmin = {x: 0, y: 0}; - rmax = {x: Number(min), y: Number(max)}; - } - x.range(rmin.x, rmax.x); - y.range(rmax.y, rmin.y); // XXX flipped? - lastLatLng = null; // invalidate the cache - return this; - } - return [rmin, rmax]; - }; - - /** - * Sets or gets the projection. This method can be invoked several ways: - * - *

1. projection(string) - * - *

Specifying a string sets the projection to the given named projection in - * {@link pv.Geo.projections}. If no such projection is found, the identity - * projection is used. - * - *

2. projection(object) - * - *

Specifying an object sets the projection to the given custom projection, - * which must implement the forward and inverse methods per the - * {@link pv.Geo.Projection} interface. - * - *

3. projection() - * - *

Invoking the projection method with no arguments returns the - * current object that defined the projection. - * - * @function - * @name pv.Scale.geo.prototype.projection - * @param {...} range... range values. - * @returns {pv.Scale.geo} this, or the current range. - */ - scale.projection = function(p) { - if (arguments.length) { - j = typeof p == "string" - ? pv.Geo.projections[p] || pv.Geo.projections.identity - : p; - return this.domain(d); // recompute normalized domain - } - return p; - }; - - /** - * Returns a view of this scale by the specified accessor function f. - * Given a scale g, g.by(function(d) d.foo) is equivalent to - * function(d) g(d.foo). This method should be used judiciously; it - * is typically more clear to invoke the scale directly, passing in the value - * to be scaled. - * - * @function - * @name pv.Geo.scale.prototype.by - * @param {function} f an accessor function. - * @returns {pv.Geo.scale} a view of this scale by the specified accessor - * function. - */ - - pv.copyOwn(scale, pv.Scale.common); - - - if (arguments.length) scale.projection(p); - return scale; -}; diff --git a/pacotes/ccc2/lib/protovis-msie.js b/pacotes/ccc2/lib/protovis-msie.js deleted file mode 100755 index 068b10d..0000000 --- a/pacotes/ccc2/lib/protovis-msie.js +++ /dev/null @@ -1,1416 +0,0 @@ -/*! - * Protovis MSIE/VML addon - * Copyright (C) 2011 by DataMarket - * Dual licensed under the terms of the MIT or GPL Version 2 software licenses. - * - * This software includes code from jQuery, http://jquery.com/ - * jQuery is licensed under the MIT or GPL Version 2 license. - * - * This software includes code from the Protovis, http://mbostock.github.com/protovis/ - * Protovis is licensed under the BSD license. - * - */ - -// detect SVG support -pv.have_SVG = !!( - document.createElementNS && - document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ).createSVGRect -); - -// detect VML support -pv.have_VML = (function (d,a,b) { - a = d.createElement('div'); - a.innerHTML = ''; - b = a.firstChild; - b.style.behavior = 'url(#default#VML)'; - return b ? typeof b.adj === 'object' : true; -})(document); - -// MSIE does not support indexOf on arrays -if ( !Array.prototype.indexOf ) { - Array.prototype.indexOf = function (s, from) { - var n = this.length >>> 0, - i = (!isFinite(from) || from < 0) ? 0 : (from > this.length) ? this.length : from; - for (; i < n; i++) { if ( this[i] === s ) { return i; } } - return -1; - }; -} - -// only run if we need to -if (!pv.have_SVG && pv.have_VML){(function(){ - -if (typeof Date.now !== 'function') { - Date.now = function () { return new Date() * 1; }; -} - -var vml = { - is64Bit: window.navigator.cpuClass === 'x64', - - round: function(n){ return Math.round( (n || 0) * 21.6 ); }, - styles: null, - - pre: '', - - block: { 'group':1, 'shape':1, 'shapetype':1, 'line':1, - 'polyline':1, 'curve':1, 'rect':1, 'roundrect':1, - 'oval':1, 'arc':1, 'image':1 }, - caps: { 'butt': 'flat', 'round': 'round', 'square': 'square' }, - joins: { 'bevel': 'bevel', 'round': 'round', 'miter': 'miter' }, - - cursorstyles: { - 'hand': 'pointer', - 'crosshair': 1, 'pointer': 1, 'move': 1, 'text': 1, - 'wait': 1, 'help': 1, 'progress': 1, - 'n-resize': 1, 'ne-resize': 1, 'nw-resize': 1, 's-resize': 1, - 'se-resize': 1, 'sw-resize': 1, 'e-resize': 1, 'w-resize': 1 - }, - - text_shim: null, - - // to be set in pv.Text.measure - - text_dims: function (text, font) { - var shim = vml.text_shim || - (vml.init(), vml.text_shim); - - shim.style.font = vml.processFont(font); - shim.innerText = text; - return { - height: shim.offsetHeight, - width: shim.offsetWidth - }; - }, - - _fontCache: {}, - - _fontSubst: { // Pass with substitution fonts - 'default': 'Arial', - // Java Logical Fonts - 'sans-serif': 'Arial', //'Microsoft Sans Serif', - 'sansserif': 'Arial', // alias - 'sans': 'Arial', // alias - 'serif': 'Times New Roman', - 'dialog': 'Arial', - 'monospaced': 'Courier New', - 'dialoginput': 'Courier New' - }, - - // IE 64 bit does not do proper fall-back of unknown fonts, - // so we decided to allow only a known subset of them. - _fontWhiteListIE64Bit: { // Allowed IE 64 bit font families - 'agency fb': 1, 'aharoni': 1, 'algerian': 1, 'andalus': 1, 'angsana new': 1, 'angsanaupc': 1, 'aparajita': 1, 'arabic typesetting': 1, 'arial': 1, 'arial black': 1, 'arial narrow': 1, 'arial rounded mt bold': 1, 'arial unicode ms': 1, 'baskerville old face': 1, 'batang': 1, 'batangche': 1, 'bauhaus 93': 1, 'bell mt': 1, 'berlin sans fb': 1, 'berlin sans fb demi': 1, 'bernard mt condensed': 1, 'blackadder itc': 1, 'bodoni mt': 1, 'bodoni mt black': 1, 'bodoni mt condensed': 1, 'bodoni mt poster compressed': 1, 'book antiqua': 1, 'bookman old style': 1, 'bookshelf symbol 7': 1, 'bradley hand itc': 1, 'britannic bold': 1, 'broadway': 1, 'browallia new': 1, 'browalliaupc': 1, 'brush script mt': 1, 'calibri': 1, 'californian fb': 1, 'calisto mt': 1, 'cambria': 1, 'cambria math': 1, 'candara': 1, 'castellar': 1, 'centaur': 1, 'century': 1, 'century gothic': 1, 'century schoolbook': 1, 'chiller': 1, 'colonna mt': 1, 'comic sans ms': 1, 'consolas': 1, 'constantia': 1, 'cooper black': 1, 'copperplate gothic bold': 1, 'copperplate gothic light': 1, 'corbel': 1, 'cordia new': 1, 'cordiaupc': 1, 'courier new': 1, 'curlz mt': 1, 'daunpenh': 1, 'david': 1, 'dfkai-sb': 1, 'dilleniaupc': 1, 'dokchampa': 1, 'dotum': 1, 'dotumche': 1, 'ebrima': 1, 'edwardian script itc': 1, 'elephant': 1, 'engravers mt': 1, 'eras bold itc': 1, 'eras demi itc': 1, 'eras light itc': 1, 'eras medium itc': 1, 'estrangelo edessa': 1, 'eucrosiaupc': 1, 'euphemia': 1, 'fangsong': 1, 'felix titling': 1, 'footlight mt light': 1, 'forte': 1, 'franklin gothic book': 1, 'franklin gothic demi': 1, 'franklin gothic demi cond': 1, 'franklin gothic heavy': 1, 'franklin gothic medium': 1, 'franklin gothic medium cond': 1, 'frankruehl': 1, 'freesiaupc': 1, 'freestyle script': 1, 'french script mt': 1, 'gabriola': 1, 'garamond': 1, 'gautami': 1, 'georgia': 1, 'gigi': 1, 'gill sans mt': 1, 'gill sans mt condensed': 1, 'gill sans mt ext condensed bold': 1, 'gill sans ultra bold': 1, 'gill sans ultra bold condensed': 1, 'gisha': 1, 'gloucester mt extra condensed': 1, 'goudy old style': 1, 'goudy stout': 1, 'gulim': 1, 'gulimche': 1, 'gungsuh': 1, 'gungsuhche': 1, 'guttman adii': 1, 'guttman adii-light': 1, 'guttman aharoni': 1, 'guttman calligraphic': 1, 'guttman david': 1, 'guttman drogolin': 1, 'guttman frank': 1, 'guttman frnew': 1, 'guttman haim': 1, 'guttman haim-condensed': 1, 'guttman hatzvi': 1, 'guttman hodes': 1, 'guttman kav': 1, 'guttman kav-light': 1, 'guttman keren': 1, 'guttman logo1': 1, 'guttman mantova': 1, 'guttman mantova-decor': 1, 'guttman miryam': 1, 'guttman myamfix': 1, 'guttman rashi': 1, 'guttman stam': 1, 'guttman stam1': 1, 'guttman vilna': 1, 'guttman yad': 1, 'guttman yad-brush': 1, 'guttman yad-light': 1, 'guttman-aharoni': 1, 'guttman-aram': 1, 'guttman-courmir': 1, 'guttman-soncino': 1, 'guttman-toledo': 1, 'haettenschweiler': 1, 'harlow solid italic': 1, 'harrington': 1, 'high tower text': 1, 'impact': 1, 'imprint mt shadow': 1, 'informal roman': 1, 'irisupc': 1, 'iskoola pota': 1, 'jasmineupc': 1, 'jokerman': 1, 'juice itc': 1, 'kaiti': 1, 'kalinga': 1, 'kartika': 1, 'khmer ui': 1, 'kodchiangupc': 1, 'kokila': 1, 'kristen itc': 1, 'kunstler script': 1, 'lao ui': 1, 'latha': 1, 'leelawadee': 1, 'levenim mt': 1, 'lilyupc': 1, 'lucida bright': 1, 'lucida calligraphy': 1, 'lucida console': 1, 'lucida fax': 1, 'lucida handwriting': 1, 'lucida sans': 1, 'lucida sans typewriter': 1, 'lucida sans unicode': 1, 'magneto': 1, 'maiandra gd': 1, 'malgun gothic': 1, 'mangal': 1, 'marlett': 1, 'matura mt script capitals': 1, 'meiryo': 1, 'meiryo ui': 1, 'microsoft himalaya': 1, 'microsoft jhenghei': 1, 'microsoft new tai lue': 1, 'microsoft phagspa': 1, 'microsoft sans serif': 1, 'microsoft tai le': 1, 'microsoft uighur': 1, 'microsoft yahei': 1, 'microsoft yi baiti': 1, 'mingliu': 1, 'mingliu-extb': 1, 'mingliu_hkscs': 1, 'mingliu_hkscs-extb': 1, 'miriam': 1, 'miriam fixed': 1, 'mistral': 1, 'modern no. 20': 1, 'mongolian baiti': 1, 'monotype corsiva': 1, 'monotype hadassah': 1, 'moolboran': 1, 'ms gothic': 1, 'ms mincho': 1, 'ms outlook': 1, 'ms pgothic': 1, 'ms pmincho': 1, 'ms reference sans serif': 1, 'ms reference specialty': 1, 'ms ui gothic': 1, 'mt extra': 1, 'mv boli': 1, 'narkisim': 1, 'niagara engraved': 1, 'niagara solid': 1, 'nsimsun': 1, 'nyala': 1, 'ocr a extended': 1, 'old english text mt': 1, 'onyx': 1, 'palace script mt': 1, 'palatino linotype': 1, 'papyrus': 1, 'parchment': 1, 'perpetua': 1, 'perpetua titling mt': 1, 'plantagenet cherokee': 1, 'playbill': 1, 'pmingliu': 1, 'pmingliu-extb': 1, 'poor richard': 1, 'pristina': 1, 'raavi': 1, 'rage italic': 1, 'ravie': 1, 'rockwell': 1, 'rockwell condensed': 1, 'rockwell extra bold': 1, 'rod': 1, 'sakkal majalla': 1, 'script mt bold': 1, 'segoe print': 1, 'segoe script': 1, 'segoe ui': 1, 'segoe ui light': 1, 'segoe ui semibold': 1, 'segoe ui symbol': 1, 'shonar bangla': 1, 'showcard gothic': 1, 'shruti': 1, 'simhei': 1, 'simplified arabic': 1, 'simplified arabic fixed': 1, 'simsun': 1, 'simsun-extb': 1, 'snap itc': 1, 'stencil': 1, 'sylfaen': 1, 'symbol': 1, 'tahoma': 1, 'tempus sans itc': 1, 'times new roman': 1, 'toptype soncino': 1, 'traditional arabic': 1, 'trebuchet ms': 1, 'tunga': 1, 'tw cen mt': 1, 'tw cen mt condensed': 1, 'tw cen mt condensed extra bold': 1, 'utsaah': 1, 'vani': 1, 'verdana': 1, 'vijaya': 1, 'viner hand itc': 1, 'vivaldi': 1, 'vladimir script': 1, 'vrinda': 1, 'webdings': 1, 'wide latin': 1, 'wingdings': 1, 'wingdings 2': 1, 'wingdings 3': 1 - }, - - _defaultFontIE64Bit: 'Arial', - - processFont: function(font){ - var processedFont = vml._fontCache[font]; - if (!processedFont) { - var shim = vml.text_shim || (vml.init(), vml.text_shim); - var style = shim.style; - style.font = font; - - var fontFamily = style.fontFamily; - if(fontFamily.charAt(0) === '"'){ - fontFamily = fontFamily.substr(1, fontFamily.length - 1); - } - - var ffKey = fontFamily.toLowerCase(); - var substFF = vml._fontSubst[ffKey]; - if(substFF){ - fontFamily = substFF; - } else if(vml.is64Bit && !vml._fontWhiteListIE64Bit[ffKey]) { - fontFamily = vml._defaultFontIE64Bit; - } - - style.fontFamily = '"' + fontFamily + '"'; - - vml._fontCache[font] = processedFont = style.font; - } - - return processedFont; - }, - - d2r: Math.PI * 2 / 360, // is this used more than once? - - get_dim: function ( attr, target ) { - var o = target || {}; - // reformat the most common attributes - o.translate_x = 0; - o.translate_y = 0; - if ( attr.transform ) { - var t = /translate\((-?\d+(?:\.\d+)?(?:e-?\d+)?)(?:,(-?\d+(?:\.\d+)?(?:e-?\d+)?))?\)/.exec( attr.transform ); //support exp - ///translate\((-?\d+(?:\.\d+)?)(?:,(-?\d+(?:\.\d+)?))?\)/.exec( attr.transform );//support negative translations - //var t = /translate\((\d+(?:\.\d+)?)(?:,(\d+(?:\.\d+)?))?\)/.exec( attr.transform ); - if ( t && t[1] ) { o.translate_x = parseFloat( t[1] ); } - if ( t && t[2] ) { o.translate_y = parseFloat( t[2] ); } - var r = /rotate\((\d+\.\d+|\d+)\)/.exec( attr.transform ); - if ( r ) { o.rotation = parseFloat( r[1] ) % 360; } - // var scale_x = 1, scale_y = 1, - // var s = /scale\((\d+)(?:,(\d+))?\)/i.exec( value ); - // if ( s && s[1] ) { scale[0] = parseInt( s[1], 10 ); } - // if ( s && s[2] ) { scale[1] = parseInt( s[2], 10 ); } - } - o.x = parseFloat( attr.x||0 ); - o.y = parseFloat( attr.y||0 ); - if ( 'width' in attr ) { - o.width = parseFloat( attr.width); - } - if ( 'height' in attr ) { - o.height = parseFloat( attr.height); - } - return o; - }, - - // constant - solidFillStyle: {type: 'solid'}, - - elm_defaults: { - - "g": { - rewrite: 'span', - attr: function ( attr, style, elm, scenes, i ) { - var d = vml.get_dim( attr ); - elm.style.cssText = "position:absolute;zoom:1;left:"+ - (d.translate_x + d.x)+"px;top:"+ - (d.translate_y + d.y)+"px;"; - } - }, - - "line": { - rewrite: 'shape', - attr: function ( attr, style, elm, scenes, i ) { - var x1 = parseFloat( attr.x1 || 0 ), - y1 = parseFloat( attr.y1 || 0 ), - x2 = parseFloat( attr.x2 || 0 ), - y2 = parseFloat( attr.y2 || 0 ), - r = vml.round; - elm.coordorigin = "0,0"; - elm.coordsize = "21600,21600"; - vml.path( elm ).v = 'M '+ r(x1) + ' ' + r(y1) + ' L ' + r(x2) + ' ' + r(y2) + ' E'; - vml.stroke( elm, attr, scenes, i ); - }, - css: "top:0px;left:0px;width:1000px;height:1000px" - }, - - "rect": { - rewrite: 'shape', - attr: function ( attr, style, elm, scenes, i ) { - var d = vml.get_dim( attr ), - p = vml.path( elm ), - r = vml.round; - elm.coordorigin = "0,0"; - elm.coordsize = "21600,21600"; - var x = r(d.translate_x + d.x), - y = r(d.translate_y + d.y), - w = r(d.width), - h = r(d.height); - p.v = 'M ' + x + ' ' + y + - ' L ' + (x + w) + ' ' + y + - ' L ' + (x + w) + ' ' + (y + h) + - ' L ' + x + ' ' + (y + h) + - ' x'; - vml.stroke( elm, attr, scenes, i ); - vml.fill( elm, attr, scenes, i ); - }, - css: "top:0px;left:0px;width:1000px;height:1000px" - }, - - "path": { - rewrite: 'shape', - attr: function ( attr, style, elm, scenes, i ) { - var d = vml.get_dim( attr ), - es = elm.style; - es.left = (d.translate_x + d.x) + "px"; - es.top = (d.translate_y + d.y) + "px"; - elm.coordorigin = "0,0"; - elm.coordsize = "21600,21600"; - elm._events = attr["pointer-events"] || 'none'; - vml.path( elm, attr.d ); - vml.fill( elm, attr, scenes, i ); - vml.stroke( elm, attr, scenes, i ); - }, - css: "top:0px;left:0px;width:1000px;height:1000px" - }, - - "circle": { - /* This version of circles is crisper but seems slower - rewrite: 'shape', - attr: function ( attr, style, elm ) { - var d = vml.get_dim( attr ), - r = vml.round( parseFloat( attr.r || 0 ) ), - cx = parseFloat( attr.cx || 0 ), - cy = parseFloat( attr.cy || 0 ), - es = elm.style; - es.left = (d.translate_x + d.x + cx + 0.3) + "px"; - es.top = (d.translate_y + d.y + cy + 0.3) + "px"; - elm.coordorigin = "0,0"; - elm.coordsize = "21600,21600"; - vml.path( elm ).v = "ar-" + r + ",-" + r + "," + r + "," + r + ",0,0,0,0x"; - vml.fill( elm, attr ); - vml.stroke( elm, attr ); - }, - css: "top:0px;left:0px;width:1000px;height:1000px" - */ - rewrite: 'oval', - attr: function ( attr, style, elm, scenes, i ) { - var d = vml.get_dim( attr ), - es = elm.style, - cx = parseFloat( attr.cx || 0 ) + 0.7, - cy = parseFloat( attr.cy || 0 ) + 0.7, - r = parseFloat( attr.r || 0 ) + 0.5; - es.top = ( d.translate_y + cy - r ) + "px"; - es.left = ( d.translate_x + cx - r ) + "px"; - es.width = ( r * 2 ) + "px"; - es.height = ( r * 2 ) + "px"; - vml.fill( elm, attr, scenes, i ); - vml.stroke( elm, attr, scenes, i ); - } - }, - - "text": { - rewrite: 'shape', - attr: function ( attr, style, elm, scenes, i ) { - var d = vml.get_dim( attr ); - var es = elm.style; - -// es.left = (d.translate_x + d.x) + "px"; -// es.top = (d.translate_y + d.y) + "px"; - -// elm.coordorigin = "0,0"; -// elm.coordsize = "21600,21600"; - - // Set stroke off, - elm.stroked = "False"; - //vml.stroke(elm, attr, scenes, i); - - elm.path = "m0,0 l1,0 e"; - - var tp = vml.textpath(elm); - tp.string = attr.string; - //tp.trim = "True"; - var tpStyle = tp.style; - tpStyle['v-text-align'] = attr.textAlign; - //tpStyle['v-text-kern' ] = 'True'; - tpStyle.font = attr.font; - - if(attr.textDecoration){ - tpStyle.textDecoration = attr.textDecoration; - } - - //tpStyle.fontWeight = "normal"; - //tpStyle.fontStyle = "normal"; - //tpStyle.xscale = "true"; - - vml.path(elm) - .textpathok = 'True'; - - // Need to set the rotation matrix - var r = attr.rotation; - if (r){ - r = 180 * r / Math.PI; - r = - (~~r % 360) * vml.d2r; - - if (r) { - var ct = Math.cos(r).toFixed(8), - st = Math.sin(r).toFixed(8); - - var skew = vml.skew(elm); - skew.on = 'true'; - skew.matrix= ct + "," + st + "," + -st + "," + ct + ",0,0"; - //elm.rotation = ~~(r / vml.d2r); // does not work - } - } - - var s = scenes[i]; - s.fillStyle = vml.solidFillStyle; - vml.fill(elm, attr, scenes, i); - s.fillStyle = null; - }, - css: "position:absolute;top:0px;left:0px;width:1px;height:1px;" - }, - - "svg": { - rewrite: 'span', - css: 'position:relative;overflow:hidden;display:inline-block;~display:block;' - }, - - // this allows reuse of the createElement function for actual VML - "vml:path": { rewrite: 'path' }, - "vml:stroke": { rewrite: 'stroke' }, - "vml:fill": { rewrite: 'fill' }, - "vml:textpath": { rewrite: 'textpath' }, - "vml:skew": { rewrite: 'skew' } - - }, - - // cloning elements is a lot faster than creating them - _elmcache: { - 'span': document.createElement( 'span' ), - 'div': document.createElement( 'div' ) - }, - - createElement: function ( type, reformat ) { - var elm, - cache = vml._elmcache, - helper = vml.elm_defaults[ type ] || {}; - var tagName = helper.rewrite || type; - if ( tagName in cache ) { - elm = cache[ tagName ].cloneNode( false ); - } - else { - cache[ tagName ] = document.createElement( vml.pre + tagName + vml.post ); - if ( tagName in vml.block ) { - cache[ tagName ].className += ' msvml_block'; - } - elm = cache[ tagName ].cloneNode( false ); - } - helper.css && (elm.style.cssText = helper.css); - return elm; - }, - - // hex values lookup table - _hex: pv.range(0,256).map(function(i){ return pv.Format.pad("0",2,i.toString(16)); }), - _colorcache: {}, - color: function (value) { - // TODO: deal with opacity here ? - var result = vml._colorcache[value]; - var rgb; - if(!result && (rgb = /^rgb\((\d+),(\d+),(\d+)\)$/i.exec(value))) { - vml._colorcache[value] = - result = - '#' + vml._hex[rgb[1]] + vml._hex[rgb[2]] + vml._hex[rgb[3]]; - } - - return result || value; - }, - - fill: function ( elm, attr, scenes, i ) { - var fill = elm.getElementsByTagName( 'fill' )[0]; - if (!fill) { - fill = elm.appendChild( vml.createElement( 'vml:fill' ) ); - } - - var fillStyle = scenes[i].fillStyle; - if (!attr.fill || !fillStyle || (fillStyle.type === 'solid' && attr.fill === 'none')) { - fill.on = 'false'; - } else { - fill.on = 'true'; - if(fillStyle.type === 'solid'){ - fill.type = 'solid'; - fill.color = vml.color(attr.fill); - } else { - var isLinear = fillStyle.type === 'lineargradient'; - fill.method = 'none'; - - var stops = fillStyle.stops; - var S = stops.length; - if(S > 0){ - var stopsText = []; - for (var i = 0 ; i < S ; i++) { - var stop = stops[i]; - stopsText.push(stop.offset + '% ' + vml.color(stop.color.color)); // TODO: color.opacity being ignored - } - - //fill.color = vml.color(stops[0].color.color); - //fill.color2 = vml.color(stops[S - 1].color.color); - if(fill.colors && typeof fill.colors === 'object'){ - fill.colors.value = stopsText.join(','); - } else { - fill.colors = stopsText.join(','); - } - } - - if(isLinear){ - // Clockwise, Top = 0, Degrees - fill.type = 'gradient'; - var angle = (-pv.degrees(fillStyle.angle)) % 360; - fill.angle = angle < 0 ? (angle + 360) : angle; - } else { - fill.type = 'gradientTitle'; - fill.focus = '100%'; - fill.focussize = '0 0'; - fill.focusposition = '0 0'; // not implemented yet - fill.angle = 0; - } - } - - fill.opacity = Math.min(parseFloat( attr['fill-opacity'] || '1' ), 1) || '1'; - } - }, - - stroke: function ( elm, attr, scenes, i ) { - var stroke = elm.getElementsByTagName('stroke')[0]; - if ( !stroke ) { - stroke = elm.appendChild( vml.createElement( 'vml:stroke' ) ); - } - if ( !attr.stroke || attr.stroke === 'none' ) { - stroke.on = 'false'; - stroke.weight = 0; - } else { - var strokeWidth = attr['stroke-width']; - if(strokeWidth == null || strokeWidth === ''){ - strokeWidth = 1; - } else { - strokeWidth = +strokeWidth; - } - - if(strokeWidth < 1e-10){ - strokeWidth = 0; - } else if (strokeWidth < 1){ - strokeWidth = 1; - } - - if(!strokeWidth){ - stroke.on = 'false'; - stroke.weight = 0; - } else { - stroke.on = 'true'; - stroke.weight = strokeWidth; - stroke.color = vml.color( attr.stroke ) || 'black'; - stroke.opacity = Math.min(parseFloat( attr['stroke-opacity'] || '1' ),1) || '1'; - stroke.joinstyle = vml.joins[ attr['stroke-linejoin'] ] || 'miter'; - stroke.miterlimit = attr['stroke-miterlimit'] || 8; - stroke.endcap = vml.caps [attr['stroke-linecap' ]] || 'flat'; - - var dashArray = attr["stroke-dasharray"]; - if(!dashArray || dashArray === 'none'){ - dashArray = 'Solid'; - } - stroke.dashstyle = dashArray; - } - } - }, - - path: function ( elm, svgpath ) { - var p = elm.getElementsByTagName( 'path' )[0]; - if ( !p ) { - p = elm.appendChild( vml.createElement( 'vml:path' ) ); - } - if ( arguments.length > 1 ) { - p.v = vml.rewritePath( svgpath ); - } - return p; - }, - - - skew: function (elm) { - var sk = elm.getElementsByTagName('skew')[0]; - if (!sk) - sk = elm.appendChild(vml.createElement('vml:skew')); - sk.on = "false"; - return sk; - }, - - textpath: function (elm) { - var tp = elm.getElementsByTagName( 'textpath') [0]; - if (!tp) { - tp = elm.appendChild(vml.createElement('vml:textpath')); - } - - tp.style['v-text-align'] = 'center'; - tp.style['v-text-kern' ] = 'true'; - tp.on = "true"; - return tp; - }, - - init: function () { - if ( !vml.text_shim ) { - vml.text_shim = document.getElementById('pv_vml_text_shim') || document.createElement('span'); - vml.text_shim.id = 'protovisvml_text_shim'; - vml.text_shim.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline-block;white-space:nowrap;"; - document.body.appendChild( vml.text_shim ); - } - - if ( !vml.styles ) { - vml.styles = document.getElementById('protovisvml_styles') || document.createElement("style"); - vml.styles.id = 'protovisvml_styles'; - document.documentElement.firstChild.appendChild( vml.styles ); - vml.styles.styleSheet.addRule( '.msvml', 'behavior:url(#default#VML);' ); - vml.styles.styleSheet.addRule( '.msvml_block', 'position:absolute;top:0;left:0;' ); - try { - if ( !document.namespaces.pvml ) { document.namespaces.add( 'pvml', 'urn:schemas-microsoft-com:vml'); } - } catch (e) { - vml.pre = '<'; - vml.post = ' class="msvml" xmlns="urn:schemas-microsoft.com:vml">'; - } - } - }, - - // SVG->VML path conversion - This converts a SVG path to a VML path - // - // Things that are missing: - // - Multiple sets of coords. - // Some commands (lineto,curveto,..) can take multiple sets of coords. - // Because Protovis always supplies the command between arguments, this isn't - // implemented, but it would be trivial to complete this. - // - ARCs need solving - _pathcache: {}, - - rewritePath:function ( p, deb ) { - var x = 0, y = 0, round = vml.round; - - if ( !p ) { return p; } - if ( p in vml._pathcache ) { return vml._pathcache[p]; } - - // clean up overly detailed fractions (8.526512829121202e-148) - p = p.replace( /(\d*)((\.*\d*)(e ?-?\d*))/g, "$1"); - - var bits = p.match( /([MLHVCSQTAZ ][^MLHVCSQTAZ ]*)/gi ); - var np = [], lastcurve = []; - var oldOp = ''; - for ( var i=0,bl=bits.length; i xx - // | - // v yy - - var dx = 0; - var dy = 0; - switch(s.textBaseline){ - case 'middle': - dy = (.1 * label.height); // slight middle baseline correction - break; - - case 'top': - dy = s.textMargin + .5 * label.height; - break; - - case 'bottom': - dy = -(s.textMargin + .5 * label.height); - break; - } - - // Text alignment is already handled by VML's textPath "v-text-align" style attribute - // So, only the text margin must be explicitly handled. - switch(s.textAlign){ - case 'left': - dx = s.textMargin; - break; - - case 'right': - dx = -s.textMargin; - break; - } - - // VML already handles rotation relative to the elements position. - // Only need to rotate the position. - var a = s.textAngle; - if(a){ - var ct = Math.cos(a); - var st = Math.sin(a); - - var dx2 = dx*ct - dy*st; - var dy2 = dx*st + dy*ct; - dx = dx2; - dy = dy2; - } - - var left = s.left + dx; - var top = s.top + dy; - - // --------------- - - var attr = {}; - if(s.cursor) { - attr.cursor = s.cursor; - } - - attr.fill = vml.color(fill.color) || "black"; - - if(vml.is64Bit){ - // The text is overly black/bold - attr['fill-opacity'] = 0.7; - } - - attr.x = left; - attr.y = top; - attr.rotation = s.textAngle; - attr.string = txt; - attr.textAlign = s.textAlign; - attr.font = font; - attr.textDecoration = s.textDecoration; - - e = this.expect(e, "text", scenes, i, attr, { - 'display': 'block', - 'lineHeight': 1, - 'whiteSpace': 'nowrap', - 'zoom': 1, - 'position': 'absolute', - 'cursor': 'default', - 'top': top + 'px', - 'left': left + 'px' - }); - - /* - e = this.expect(e, "text", scenes, i, attr, { - "font": s.font, - // "text-shadow": s.textShadow, - "textDecoration": s.textDecoration, - 'top': Math.round( s.top + dy ) + 'px', - 'left': Math.round( s.left + dx ) + 'px', - 'position': 'absolute', - 'display': 'block', - 'lineHeight': 1, - 'whiteSpace': 'nowrap', - 'zoom': 1, - 'cursor': 'default', - 'color': vml.color( fill.color ) || 'black' - }); - e.innerText = txt; - */ - - -/* - // Rotation is broken in several different ways: - // 1. it looks REALLY ugly - // 2. it is incredibly slow - // 3. rotated text is offset completely wrong and it takes a ton of math to correct it - // when text is rotated we need to switch to a VML textpath solution - var rotation = 180 * s.textAngle / Math.PI; - if ( rotation ) { - var r = (~~rotation % 360) * vml.d2r, - ct = Math.cos(r), - st = Math.sin(r); - e.style.filter = ['progid:DXImageTransform.Microsoft.Chroma(color="white") progid:DXImageTransform.Microsoft.Matrix(', - 'M11=', ct.toFixed( 8 ), ',', - 'M12=', -st.toFixed( 8 ), ',', - 'M21=', st.toFixed( 8 ), ',', - 'M22=', ct.toFixed( 8 ), ',sizingMethod=\'auto expand\')";'].join(''); - e.style.backgroundColor = "white"; - } else { - e.style.filter = ''; - } -*/ - e = this.append(e, scenes, i); - } - return e; -}; - -pv.VmlScene.wedge = function(scenes) { - var e = scenes.$g.firstChild, - round = vml.round; - for (var i = 0; i < scenes.length; i++) { - var s = scenes[i]; - - // visible - if (!s.visible) continue; - var fill = s.fillStyle, stroke = s.strokeStyle; - if (!fill.opacity && !stroke.opacity) continue; - - // create element sans path - e = this.expect(e, "path", scenes, i, { - "pointer-events": s.events, - "cursor": s.cursor, - "transform": "translate(" + s.left + "," + s.top + ")", - "d": '', // we deal with the path afterwards - "fill": fill.color, - "fill-rule": "evenodd", - "fill-opacity": fill.opacity || null, - "stroke": stroke.color, - "stroke-opacity": stroke.opacity || null, - "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null, - "stroke-linecap": s.lineCap, - "stroke-linejoin": s.lineJoin, - "stroke-miterlimit": s.strokeMiterLimit, - "stroke-dasharray": stroke.opacity ? this.parseDasharray(s) : null - }); - - // add path - var p = e.getElementsByTagName( 'path' )[0]; - if ( !p ) { - p = vml.make( 'path' ); - e.appendChild( p ); - } - - // Arc path from bigfix/protovis - var r1 = round(s.innerRadius), - r2 = round(s.outerRadius), - d; - if (s.angle >= 2 * Math.PI) { - if (r1) { - d = "AE0,0 " + r2 + "," + r2 + " 0 23592960" - + "AL0,0 " + r1 + "," + r1 + " 0 23592960"; - } - else { - d = "AE0,0 " + r2 + "," + r2 + " 0 23592960"; - } - } - else { - var sa = Math.round(s.startAngle / Math.PI * 11796480), - a = Math.round(s.angle / Math.PI * 11796480); - if (r1) { - d = "AE 0,0 " + r2 + "," + r2 + " " + -sa + " " + -a - + " 0,0 " + r1 + "," + r1 + " " + -(sa + a) + " " + a - + "X"; - } - else { - d = "M0,0" - + "AE0,0 " + r2 + "," + r2 + " " + -sa + " " + -a - + "X"; - } - } - p.v = d; - - e = this.append(e, scenes, i); - - } - return e; -}; - -// end VML override -})();} diff --git a/pacotes/ccc2/lib/tipsy.css b/pacotes/ccc2/lib/tipsy.css deleted file mode 100755 index 232b701..0000000 --- a/pacotes/ccc2/lib/tipsy.css +++ /dev/null @@ -1,33 +0,0 @@ -.tipsy { pointer-events: none; padding: 5px; font-size: 10px; font-family: Arial,Helvetica,sans-serif; position: absolute; z-index: 100000; } - .tipsy-inner { padding: 5px 8px 4px 8px; background-color: black; color: white; max-width: 200px; text-align: center; } - .tipsy-inner { border-radius: 3px; -moz-border-radius:3px; -webkit-border-radius:3px; } - - /* Uncomment for shadow */ - /*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/ - - .tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; } - - .tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; } - .tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} - .tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} - - .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } - .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } - .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } - - .tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; } - .tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; } - - /* - Corner arrow styles. - .tipsy-nww .tipsy-arrow { left: 0; top: 10px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; } - .tipsy-nee .tipsy-arrow { right: 0; top: 10px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; } - .tipsy-sww .tipsy-arrow { right: 0; top: 10px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; } - .tipsy-see .tipsy-arrow { right: 0; bottom: -10px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent;} - */ - - /* - .tipsy-arrow { border-color: green; } - .tipsy { border-width: 1px; border-style:solid; border-color:red;} - - */ \ No newline at end of file diff --git a/pacotes/ccc2/lib/tipsy.js b/pacotes/ccc2/lib/tipsy.js deleted file mode 100755 index 8bd40eb..0000000 --- a/pacotes/ccc2/lib/tipsy.js +++ /dev/null @@ -1,709 +0,0 @@ -(function(){ - - var _nextTipsyId = 0; - - pv.Behavior.tipsy = function(opts) { - var _tipsyId = _nextTipsyId++; - - /** - * One tip is reused per behavior instance. - * Typically there is one behavior instance per mark, - * and this is reused across all its mark instances. - */ - - if(!opts) { - opts = {}; - } else { - opts = Object.create(opts); - } - - /** - * Trigger must be manual because the mouse entering/leaving - * the **fake target** is not always adequate. - * - * When followMouse=true, the fake target is always moving, and is not usable - * for bounds control. What matters is the real SVG target. - */ - opts.trigger = 'manual'; - - /** - * Gravity is intercepted to allow for off screen bounds reaction. - */ - var _userGravity = opts.gravity || $.fn.tipsy.defaults.gravity; - var _userGravityFun; - if(typeof _userGravity === 'function'){ - _userGravityFun = _userGravity; - _userGravity = null; - } - - opts.gravity = calculateGravity; - - var $fakeTipTarget, // target div - $targetElem, - nextOperationId = 0, - prevMouseX, - prevMouseY, - _renderId, - _mark, - delayOut = opts.delayOut, - id, - usesPoint = opts.usesPoint, - $canvas, - isEnabled = opts.isEnabled, - sharedTipsyInfo; - - opts.delayOut = 0; - - function getTooltipText() { - var instance = _mark.instance(); - var title = (instance && instance.tooltip) || - // A mark method that is not a property? - (!_mark.properties.tooltip && typeof _mark.tooltip == 'function' && _mark.tooltip()) || - instance.title || - instance.text; - - // Allow deferred tooltip creation! - if(typeof title === 'function') { - title = title(); - } - - return title || ""; // Prevent "undefined" from showing up - } - - function getInstanceBounds() { - var instance = _mark.instance(); - - /* - * Compute bounding box. - * TODO: support area, lines. - */ - var left, top, width, height; - if (_mark.properties.width) { - // Bar, panel - var bounds = getVisibleScreenBounds(_mark); - - left = bounds.left; - top = bounds.top; - width = bounds.width; - height = bounds.height; - - } else { - /* Compute the transform to offset the tooltip position. */ - var t = _mark.toScreenTransform(); - var radius; - if(_mark.properties.outerRadius){ - // Wedge - var midAngle = instance.startAngle + instance.angle / 2; - radius = instance.outerRadius;// - (instance.outerRadius - instance.innerRadius) * 0.05; - - left = t.x + instance.left + radius * Math.cos(midAngle); - top = t.y + instance.top + radius * Math.sin(midAngle); - - } else if(_mark.properties.shapeRadius){ - radius = Math.max(2, instance.shapeRadius); - var cx = instance.left; - var cy = instance.top; - - switch(instance.shape){ - case 'diamond': - radius *= Math.SQRT2; - // NOTE fall through - break; - - case 'circle': - // Want the inscribed square - radius /= Math.SQRT2; - break; - } - - left = (cx - radius) * t.k + t.x; - top = (cy - radius) * t.k + t.y; - height = width = 2*radius * t.k; - - - } else { - left = instance.left * t.k + t.x; - top = instance.top * t.k + t.y; - } - } - - var left2 = Math.ceil(left); - var top2 = Math.ceil(top); - - var leftE = left2 - left; // >= 0 / < 1 - var topE = top2 - top; // >= 0 / < 1 - - width = Math.max(1, Math.floor((width || 0) - leftE)); - height = Math.max(1, Math.floor((height || 0) - topE )); - - return { left: left2, top: top2, width: width, height: height }; - } - - // ------------------- - // TIPSY Gravity - - /** - * Gravity is the direction of the tooltip arrow. - * The arrow points to the target element. - * - * gravity = 'w' - * +-----------+ n - * | | +----+----+ - * | | | | - * | target | w <=+ Tooltip + e - * | | | | - * | | +----+----+ - * +-----------+ s - * - */ - - var _gravities = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w']; - - function updateUserGravity(){ - if(_userGravityFun){ - _userGravity = _userGravityFun.call(_mark) || $.fn.tipsy.defaults.gravity; - } - - return _userGravity; - } - - function calculateGravity(tipSize, calcPosition){ - /*jshint expr:true */ - - // - // jquery.tipsy calls this on the element to which it is attached - (this === $fakeTipTarget[0]) || def.assert(); - // - - var $win = $(window); - var scrollOffset = {width: $win.scrollLeft(), height: $win.scrollTop()}; - var pageSize = {width: $win.width(), height: $win.height() }; - - // Desired gravity (assumes updateUserGravity was called previously) - var gravity = _userGravity; - - // backwards compatibility for special gravity, 'c', - // added to jquery.tipsy to avoid the style applying to the arrow, - // causing it to not show. - if(gravity === 'c'){ - gravity = 'w'; - } - - var bestScore = scoreGravity(gravity); - if(!bestScore.isTotal){ - // Find the best scored gravity. - // Start from the position *after* 'gravity' in the gravities array, - // turning around when the end is reached. - - var g = _gravities.indexOf(gravity); - for(var n = 1, L = _gravities.length ; n < L ; n++){ - var i = (g + n) % L; - bestScore = chooseScores(bestScore, scoreGravity(_gravities[i])); - } - - if(_tip.debug >= 6 && gravity !== bestScore.gravity){ - _tip.log("[TIPSY] #" + _tipsyId + " Choosing gravity '" + bestScore.gravity + "' over '" + gravity + "'"); - } - - gravity = bestScore.gravity; - } - - if(_tip.debug >= 6){ - _tip.log("[TIPSY] #" + _tipsyId + " Gravity '" + gravity + "'"); - } - - return gravity; - - function scoreGravity(gravity){ - var tp = calcPosition(gravity); - return scorePosition(gravity, tp); - } - - function scorePosition(gravity, tp){ - var wScore = calcPosScore(tp.left, 'width' ); - var hScore = calcPosScore(tp.top, 'height'); - var isTotal = wScore.fits && hScore.fits; - - return { - gravity: gravity, - width: wScore, - height: hScore, - value: wScore.value + hScore.value + (2 - gravity.length), // prefer simple gravities - isTotal: isTotal, - isPartial: !isTotal && (wScore.fits || hScore.fits) - }; - } - - function calcPosScore(absPos, a_len){ - /*global window:true*/ - var maxLen = pageSize[a_len]; - var len = tipSize[a_len]; - - var pos = absPos - scrollOffset[a_len]; - var opos = maxLen - (pos + len); - var fits = pos >= 0 && opos >= 0; - - // Negative positions (off-screen) are amplified 4 times - // so that they negatively impact the score more than positive ones. - var value = (pos >= 0 ? pos : (4 * pos)) + - (opos >= 0 ? opos : (4 * opos)); - - return {fits: fits, value: value}; - } - } - - function chooseScores(score1, score2){ - if(score1.isTotal){ - if(!score2.isTotal){ - return score1; - } - } else if(score2.isTotal){ - if(!score1.isTotal){ - return score2; - } - } else if(score1.isPartial){ - if(!score2.isPartial){ - return score1; - } - } else if(score2.isPartial){ - if(!score1.isPartial){ - return score2; - } - } - - // Are of same type. Can compare values. - return score2.value > score1.value ? score2 : score1; - } - - /* - * Places and sizes the tip target div - * on the specified bounds. - * - * Tipsy gravities point to this div. - */ - function setFakeTipTargetBounds(bounds) { - $fakeTipTarget.css({ - left: bounds.left + parseFloat($canvas.css("padding-left")), - top: bounds.top + parseFloat($canvas.css("padding-top" )), - width: bounds.width, - height: bounds.height - }); - } - - function createTipsy(mark) { - var c = mark.root.canvas(); - - $canvas = $(c); - - c.style.position = "relative"; - $canvas.mouseleave(hideTipsy); - - // ------------ - - initTipsyCanvasSharedInfo(); - - // ------------ - - /* Use the specified div id or create a hopefully unique one */ - if(!id){ - id = "tipsyPvBehavior_" + new Date().getTime(); - } - - /*global document:true*/ - var fakeTipTarget = document.getElementById(id); - if(!fakeTipTarget) { - fakeTipTarget = document.createElement("div"); - fakeTipTarget.id = id; - c.appendChild(fakeTipTarget); - } - - var fakeStyle = fakeTipTarget.style; - fakeStyle.padding = '0px'; - fakeStyle.margin = '0px'; - fakeStyle.position = 'absolute'; - fakeStyle.pointerEvents = 'none'; // ignore mouse events (does not work on IE) - fakeStyle.display = 'block'; - fakeStyle.zIndex = -10; - - $fakeTipTarget = $(fakeTipTarget); - - updateTipDebug(); - - // Create the tipsy instance - $fakeTipTarget.data('tipsy', null); // Otherwise a new tipsy is not created, if there's one there already - $fakeTipTarget.tipsy(opts); - } - - function initTipsyCanvasSharedInfo(){ - sharedTipsyInfo = $canvas.data('tipsy-pv-shared-info'); - if(sharedTipsyInfo){ - var createId = ($canvas[0].$pvCreateId || 0); - - if(sharedTipsyInfo.createId === createId){ - sharedTipsyInfo.behaviors.push(hideTipsyOther); - return; - } - - // Protovis has recreated the whole structure - // So all existing tipsies (but this one) are invalid... - // Hide them and let GC do the rest - sharedTipsyInfo.behaviors.forEach(function(aHideTipsy){ - aHideTipsy(); - }); - } - - - sharedTipsyInfo = { - createId: ($canvas[0].$pvCreateId || 0), - behaviors: [hideTipsyOther] - }; - - $canvas.data('tipsy-pv-shared-info', sharedTipsyInfo); - } - - function updateTipDebug(){ - if($fakeTipTarget){ - if(_tip.debug >= 16){ - $fakeTipTarget.css({ - borderColor: 'red', - borderWidth: '1px', - borderStyle: 'solid', - zIndex: 1000 - }); - } else { - $fakeTipTarget.css({ - borderWidth: '0px', - zIndex: -10 - }); - } - } - } - - function getMouseBounds(ev){ - if(!ev){ ev = pv.event; } - - var delta = 5; - var offset = $canvas.offset(); - return { - left: ev.pageX - offset.left - delta, - top: ev.pageY - offset.top - delta, - width: 10 + 2*delta, - height: 20 - }; - } - - function setTarget(targetElem, mark){ - - if((!$targetElem && targetElem) || - ( $targetElem && $targetElem[0] !== targetElem)){ - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Changing target element."); } - - if($targetElem){ - $targetElem.unbind('mousemove', updateTipsy); - - if(!usesPoint) { - $targetElem.unbind('mouseleave', hideTipsy); - } - } - - // --------- - - $targetElem = targetElem ? $(targetElem) : null; - _mark = targetElem ? mark : null; - - prevMouseX = prevMouseY = _renderId = null; - - // --------- - - if($targetElem){ - $targetElem.mousemove(updateTipsy); - - if(!usesPoint) { - $targetElem.mouseleave(hideTipsy); - } - } - } - } - - function getNewOperationId(){ - return nextOperationId++; - } - - function checkCanOperate(opId){ - return opId === nextOperationId - 1; - } - - function hideTipsy() { - var opId = getNewOperationId(); - - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Delayed Hide Begin opId=" + opId); } - - if(delayOut > 0){ - window.setTimeout(function(){ - if(checkCanOperate(opId)){ - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Hiding opId=" + opId + " nextOperationId=" + nextOperationId); } - hideTipsyCore(opId); - } else { - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Delayed Hide Cancelled opId=" + opId); } - } - }, delayOut); - - return; - } - - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Hiding Immediately opId=" + opId); } - hideTipsyCore(opId); - } - - function hideTipsyOther() { - var opId = getNewOperationId(); - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Hiding as Other opId=" + opId); } - hideTipsyCore(opId); - } - - function hideTipsyCore(opId) { - // Release real target - setTarget(null, null); - - if ($fakeTipTarget) { - $fakeTipTarget.tipsy("leave"); - } - } - - function hideOtherTipsies(){ - var hideTipsies = sharedTipsyInfo && sharedTipsyInfo.behaviors; - if(hideTipsies && hideTipsies.length > 1){ - hideTipsies.forEach(function(aHideTipsy){ - if(aHideTipsy !== hideTipsyOther){ - aHideTipsy(); - } - }); - } - } - - function updateTipsy(ev){ - if(!$fakeTipTarget) { - return; - } - - /* Don't know why: - * the mouseover event is triggered at a fixed interval - * as long as the mouse is over the element, - * even if the mouse position does not change... - */ - if(prevMouseX != null && - Math.abs(ev.clientX - prevMouseX) < 3 && - Math.abs(ev.clientY - prevMouseY) < 3){ - return; - } - - var tag = this.$scene; - // tag = {scenes: scenes, index: index} - // instance = scenes[index]; - // mark = scenes.mark; - - var scenes; - if(!tag || !(scenes = tag.scenes) || !scenes.mark || (scenes.mark !== _mark)){ - return; - } - - var renderId = _mark.renderId(); - var renderIdChanged = (renderId !== _renderId); - var followMouse = opts.followMouse; - - if(!followMouse && !renderIdChanged){ - return; - } - - var opId = getNewOperationId(); - - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Updating opId=" + opId); } - - prevMouseX = ev.clientX; - prevMouseY = ev.clientY; - - // ------------- - - var bounds; - if(followMouse){ - bounds = getMouseBounds(ev); - } - - if(renderIdChanged){ - // => update bounds, text and gravity - - _renderId = renderId; - - // Position is updated because, - // otherwise, animations that re-render - // the hovering mark causing it to move, - // in a way that the mouse is still kept inside it, - // we have to update the position of the tooltip as well. - - _mark.context(scenes, tag.index, function(){ - - if(!followMouse){ - bounds = getInstanceBounds(); - } - - var text = getTooltipText(); - - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Update text. Was hidden. Text: " + text); } - - $fakeTipTarget.tipsy('setTitle', text); // does not update the tooltip UI - - updateUserGravity(); - }); - } - - setFakeTipTargetBounds(bounds); - - hideOtherTipsies(); - - $fakeTipTarget.tipsy("update"); - } - - function initBehavior(mark){ - // First time - - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Creating"); } - - createTipsy(mark); - - /* Cleanup the tooltip span on mouseout. - * This is necessary for dimensionless marks. - * - * Note that the tip has pointer-events disabled - * (so as to not interfere with other mouse events, such as "click"); - * thus the mouseleave event handler is registered on - * the event target rather than the tip overlay. - */ - if(usesPoint){ - // Behavior is being used as a 'point' event handler - // Should hide the tipsy only in the unpoint event - mark.event('unpoint', hideTipsy); - } - } - - function showTipsy(mark) { - var opId = getNewOperationId(); - - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Show IN opId=" + opId); } - - if (!$canvas) { - initBehavior(mark); - } - - var isHidden = !$targetElem; - - setTarget(pv.event.target, mark); - - var text = getTooltipText(); - - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Text: " + text); } - - $fakeTipTarget.tipsy('setTitle', text); - - setFakeTipTargetBounds(opts.followMouse ? getMouseBounds() : getInstanceBounds()); - - updateUserGravity(); - - hideOtherTipsies(); - - if(isHidden){ - $fakeTipTarget.tipsy('enter'); - } else { - $fakeTipTarget.tipsy('update'); - } - - if(_tip.debug >= 4){ _tip.log("[TIPSY] #" + _tipsyId + " Show OUT"); } - } - - // On 'point' or 'mouseover' events, according to usesPoint option - function tipsyBehavior() { - // The mark that the tipsy-behavior is attached to - var mark = this; - - if(!isEnabled || isEnabled(tipsyBehavior, mark)){ - showTipsy(mark); - } - } - - return tipsyBehavior; - }; // END pv.Behavior.tipsy - - var _tip = pv.Behavior.tipsy; - _tip.debug = 0; - _tip.setDebug = function(level){ - _tip.debug = level; - }; - - _tip.log = function(m){ - /*global console:true*/ - if(typeof console !== "undefined"){ - console.log('' + m); - } - }; - - function toParentTransform(parentPanel){ - return pv.Transform.identity. - translate(parentPanel.left(), parentPanel.top()). - times(parentPanel.transform()); - } - - function getVisibleScreenBounds(mark){ - - var instance = mark.instance(), - left = instance.left, - top = instance.top, - width = instance.width, - height = instance.height, - right, - bottom, - parent; - - while ((parent = mark.parent)){ - - // Does 'mark' fit in its parent? - if(left < 0){ - width += left; - left = 0; - } - - if(top < 0){ - height += top; - top = 0; - } - - right = instance.right; - if(right < 0){ - width += right; - } - - bottom = instance.bottom; - if(bottom < 0){ - height += bottom; - } - - // Transform to parent coordinates - var t = toParentTransform(parent), - s = t.k; - - left = t.x + (s * left); - top = t.y + (s * top ); - width = s * width; - height = s * height; - - mark = parent; - instance = mark.instance(); - } - - return { - left: left, - top: top, - width: width, - height: height - }; - } - -}()); \ No newline at end of file diff --git a/pacotes/ccc2/licenca.txt b/pacotes/ccc2/licenca.txt deleted file mode 100755 index dab0062..0000000 --- a/pacotes/ccc2/licenca.txt +++ /dev/null @@ -1,341 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. -- \ No newline at end of file diff --git a/pacotes/ccc2/pvc-r2.0.js b/pacotes/ccc2/pvc-r2.0.js deleted file mode 100644 index c8560b5..0000000 --- a/pacotes/ccc2/pvc-r2.0.js +++ /dev/null @@ -1,728 +0,0 @@ -/*! - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -//VERSION 13.06.05 - -var pvc=function(f,u){function Ra(){if(i.debug&&typeof console!=="undefined")["log","info",["trace","debug"],"error","warn",["group","groupCollapsed"],"groupEnd"].forEach(function(a){a=a instanceof Array?a:[a,a];va(i,a[0],a[1],"[pvChart]")});else{if(i.debug>1)i.debug=1;["log","info","trace","warn","group","groupEnd"].forEach(function(a){i[a]=f.noop});i.error=function(a){if(a&&typeof a==="object"&&a.message)a=a.message;a=""+f.nullyTo(a,"");if(a.indexOf("[pvChart ERROR]: ")<0)a="[pvChart ERROR]: "+ -a;throw new Error(a);}}i.logError=i.error;u.error=i.error}function Sa(){var a=u.Behavior.tipsy;if(a&&a.setDebug){a.setDebug(i.debug);a.log=i.log}}function va(a,b,c,d){c||(c=b);var e=console,g=e[c]||e.log,h;if(g){var j=d+": %s";if(f.fun.is(g))h=g.bind(e,j);else{var l=Function.prototype.apply;h=function(){l.call(g,e,f.array.append([j],arguments))}}}a[b]=h}function Ta(a,b){if(a){if(f.object.is(a))return a.abs;return b?b+f.firstUpperCase(a):a}return b}function wa(a){a=u.color(a);var b=a.r,c=a.g;a=a.b; -var d=(b+c+a)/3;return Math.abs(b-d)<=2&&Math.abs(c-d)<=2&&Math.abs(a-d)<=2}function xa(a){a||f.fail.argumentRequired("keyArgs");var b=a.type||f.fail.argumentRequired("keyArgs.type");switch(b){case "linear":return(new i.color.LinearScalesBuild(a)).buildMap();case "discrete":return(new i.color.DiscreteScalesBuild(a)).buildMap();case "normal":return(new i.color.NormalScalesBuild(a)).buildMap()}throw f.error.argumentInvalid("scaleType","Unexistent scale type '{0}'.",[b]);}function ya(a){a||f.fail.argumentRequired("keyArgs"); -var b=a.type||f.fail.argumentRequired("keyArgs.type");switch(b){case "linear":return(new i.color.LinearScalesBuild(a)).build();case "discrete":return(new i.color.DiscreteScalesBuild(a)).build();case "normal":return(new i.color.NormalScalesBuild(a)).build()}throw f.error.argumentInvalid("scaleType","Unexistent scale type '{0}'.",[b]);}function ea(a,b){function c(o){return(f.getOwn(n,o)||f.fail.operationInvalid("Undefined option '{0}'",[o])).resolve()}function d(o,p){o=c(o);return p&&!o.isSpecified? -undefined:o.value}function e(o){return c(o).isSpecified}function g(o){return d(o,true)}function h(o){return f.hasOwn(n,o)}function j(o){return k(o,false)}function l(o){return k(o,true)}function m(o){return c(o)._defaultValue}function k(o,p){for(var q in o){var s=f.getOwn(n,q);if(s){var r=o[q];r!==undefined&&s.set(r,p)}}return d}a||f.fail.argumentRequired("specs");var n={};f.each(a,function(o,p){o=new Ua(p,d,b,o);n[o.name]=o});d.option=d;d.specified=g;d.isSpecified=e;d.isDefined=h;d.defaultValue=m; -d.specify=j;d.defaults=l;return d}function Va(a){return function(b){for(var c=0,d=a.length;c=a.length?a.push(c):a.splice(e,0,c)}function ka(a,b,c,d){c&&(!c[d]||c[d]===a)||f.assert("Not a child");if(a=a[b]){b=a.indexOf(c);b>=0&&f.array.removeAt(a,b)}c[d]=null}function Za(a){this.playedVisualRoles.set(a.name,a);za.call(this.complexType,this)}function $a(a){this.playedVisualRoles.rem(a.name);za.call(this.complexType,this)}function za(){this._isPctRoleDimTypeMap= -null}function ab(a,b){function c(){var e={},g=f.query(d.source).select(function(h){b(h,e);h=e.series;if(h!=null&&h.v!=null)h=h.v;return h||null}).distinct().array();return d._createPlot2SeriesKeySet(a,g)}var d=this;return this._dataPartGet(c,b)}function bb(a,b){return a.id-b.id}function cb(a,b){return b.id-a.id}function Aa(){delete this.isSelected}function db(a){return a.isNull||a.isSelected}function Ba(a,b,c,d,e,g){if(this.owner===this){if(e==null)e=(a=a._formatter)?a(d,b):d;e=""+e;!e&&i.debug>= -2&&i.log("Only the null value should have an empty label.");b=new i.data.Atom(this,d,e,b,c);if(g)b.isVirtual=true}else{var h=this.parent||this.linkParent;b=h._atomsByKey[c]||Ba.call(h,a,b,c,d,e,g)}f.array.insert(this._atoms,b,this._atomComparer);fa.call(this);return this._atomsByKey[c]=b}function Ca(a){var b=a.key;if(a.dimension===this){this.owner===this||f.assert("Should be an owner dimension");if(!b&&a===this._virtualNullAtom)a=this.intern(null);return a}if(!this._lazyInit){var c=this._atomsByKey[b]; -if(c){if(c!==a)throw f.error.operationInvalid("Atom is from a different root data.");return a}if(this.owner===this)throw f.error.operationInvalid("Atom is from a different root data.");}Ca.call(this.parent||this.linkParent,a);if(!this._lazyInit){this._atomsByKey[b]=a;if(b)f.array.insert(this._atoms,a,this._atomComparer);else{this._nullAtom=a;this._atoms.unshift(a)}fa.call(this)}return a}function Da(a){var b=f.get(a,"visible");a=f.get(a,"selected");return(b==null?null:!!b)+":"+(a==null?null:!!a)}function ga(a){var b= -this._nullAtom;if(!b){if(this.owner===this){b=this.type._formatter;a=""+(b?b.call(null,null,a):"");b=new i.data.Atom(this,null,a,null,"");this.data._atomsBase[this.name]=b}else b=ga.call(this.parent||this.linkParent,a);this._atomsByKey[""]=this._nullAtom=b;this._atoms.unshift(b)}return b}function eb(){this.owner===this||f.assert("Can only create atoms on an owner dimension.");if(!this._virtualNullAtom){this._virtualNullAtom=new i.data.Atom(this,null,"",null,"");this.data._atomsBase[this.name]=this._virtualNullAtom}return this._virtualNullAtom} -function fb(){this.owner===this||f.assert("Can only unintern atoms of an owner dimension.");var a=this._atoms;if(a){for(var b=this._atomsByKey,c=0,d=a.length;c0||f.assert("Must have had accounted for at least one visible datum.");c[a]=(d||0)+(b?1:-1);this._visibleAtoms=this._sumCache=this._visibleIndexes=null}}function mb(){var a=this._atomVisibleDatumsCount;if(!a){a={};this.data.datums(null,{visible:true}).each(function(b){b=b.atoms[this.name].key;a[b]=(a[b]||0)+1},this);this._atomVisibleDatumsCount=a}return a} -function nb(a){var b=[];this._atoms.forEach(function(c,d){this.isVisible(c)===a&&b.push(d)},this);return b}function ob(a){return f.query(this._atoms).where(function(b){return this.isVisible(b)===a},this).array()}function pb(a,b){this.insertAt(a,b);f.lazy(this,"_childrenByKey")[a.key]=a}function qb(a,b){ja(this,"_linkChildren",a,"linkParent",b)}function rb(a){ka(this,"_linkChildren",a,"linkParent")}function la(){ia(this._children,"parent");this._childrenByKey=null;ia(this._linkChildren,"linkParent"); -this._sumAbsCache=this._groupByCache=null}function Ea(){this.isOwner()||f.fail("Can only be called on the owner data.")}function sb(a,b){!a.isNull||f.assert("Null datums do not notify selected changes");b?this._selectedNotNullDatums.set(a.id,a):this._selectedNotNullDatums.rem(a.id);this._sumAbsCache=null}function ma(a,b){if(f.hasOwn(this._datumsById,a.id)){!a.isNull||f.assert("Null datums do not notify visible changes");b?this._visibleNotNullDatums.set(a.id,a):this._visibleNotNullDatums.rem(a.id); -this._sumAbsCache=null;f.eachOwn(this._dimensions,function(c){lb.call(c,a,b)});this._children.forEach(function(c){ma.call(c,a,b)});this._linkChildren&&this._linkChildren.forEach(function(c){ma.call(c,a,b)})}}function tb(a,b){f.string.is(a)||f.fail.argumentInvalid("groupLevelText","Invalid grouping specification.");return f.query(a.split(/\s*\|\s*/)).where(f.truthy).select(function(c){var d=ub.exec(c)||f.fail.argumentInvalid("groupLevelText","Invalid grouping level syntax '{0}'.",[c]);c=d[1];d=(d[2]|| -"").toLowerCase()==="desc";return new i.data.GroupingDimensionSpec(c,d,b)})}function na(a,b){function c(s){if(s){var r=s.key;if(!f.hasOwnProp.call(j,r)){if(l){var t=f.getOwn(l,r);if(t){if(e)return;s=t}}j[r]=s;r=s.id;k[r]=s;oa.call(this,s,!!this._dimensions,d);if(!s.isNull){h&&s.isSelected&&h.set(r,s);s.isVisible&&g.set(r,s)}return s}}}a||f.fail.argumentRequired("newDatums");var d=f.get(b,"doAtomGC",false),e=f.get(b,"isAdditive",false),g=this._visibleNotNullDatums,h=this._selectedNotNullDatums,j={}, -l;if(b=this._datums){var m=e&&d;l=f.query(b).uniqueIndex(function(s){m&&oa.call(this,s,false,true);return s.key},this);if(e)this._sumAbsCache=null;else{la.call(this);h&&h.clear();g.clear()}}else e=false;var k;k=e?this._datumsById:(this._datumsById={});if(f.array.is(a))for(var n=0,o=a.length;n=0)throw f.error.argumentInvalid("keyArgs.orderBy","Multi-dimension order by is not supported.");}else c=Object.keys(a).sort().join(",");var d=this.groupBy(c, -b),e=d.treeHeight,g=[];return f.query(function(){var h;if(this._data){if(this._datumsQuery){this._data||f.assert("Must have a current data");g.length||f.assert("Must have a parent data");!this._dimAtomsOrQuery||f.assert();if(this._datumsQuery.next()){this.item=this._datumsQuery.item;return 1}this._datumsQuery=null;h=g.pop();this._data=h.data;this._dimAtomsOrQuery=h.dimAtomsOrQuery}}else{this._data=d;this._dimAtomsOrQuery=f.query(a[d._groupLevelSpec.dimensions[0].name])}this._dimAtomsOrQuery||f.assert("Invalid programmer"); -this._data||f.assert("Must have a current data");var j=g.length;do{for(;this._dimAtomsOrQuery.next();)if((h=this._data._childrenByKey[this._dimAtomsOrQuery.item.key])&&(j=0&&(e=c[d]))b._inContext(e.data,e);return b}function zb(a){var b;do a=a.parent;while(a&&!(b=a.sign)&&(!a.proto||!(b=a.proto.sign)));return b}function La(a){return a.isDiscrete()?"discrete":a.firstDimensionValueType()===Date?"timeSeries":"numeric"}function Ab(a,b){return i.parseDomainScope(a,b.orientation)}function Bb(a){if(a){if(f.hasOwn(F.namesSet,a))return i.BasePanel[this.orientation==="y"?"horizontalAlign":"verticalAlign2"][a];i.debug>=2&&i.log(f.format("Invalid axis position value '{0}'.", -[a]))}return this.orientation==="x"?"bottom":"left"}function Ma(a){var b=this.option("Position");return M.toOrtho(a,b)}function Na(a){var b=this.option("Position");return M.to(a,{singleProp:i.BasePanel.orthogonalLength[b]})}function Cb(a){var b;if(a){var c;f.eachOwn(a,function(d,e){c=true;a[e]=u.color(d)});if(c)b=a}return b}function Db(){var a;if(a=this.scaleType)if(a==="discrete")if(this.index===0)a=i.createColorScheme();else{var b=this;a=function(){return b.chart._getRoleColorScale(b.role.name)}}else{ra|| -(ra=["red","yellow","green"].map(u.color));a=ra.slice()}else a=i.createColorScheme();return a}function Oa(a){if(!f.object.is(a)){var b=this.option("Position");a=(new M).setSize(a,{singleProp:i.BasePanel.orthogonalLength[b]})}return a}function Eb(a){var b=this.option("Position");return i.parseAlign(b,a)}function Fb(a){if(this.name==="trend")return null;var b=this.option("TrendType");if(!b&&a)b=a.type;if(!b||b==="none")return null;a=a?Object.create(a):{};a.type=b;b=this.option("TrendLabel");if(b!== -undefined)a.label=b;return a}function sa(a,b){return{resolveV1:function(c){if(this.globalIndex===0){this._specifyChartOption(c,"show"+a)||c.defaultValue(b);return true}}}}function Pa(a){return{resolveV1:function(b){this._specifyChartOption(b,"show"+a);return true}}}var i=f.globalSpace("pvc",{debug:0});(function(){if(typeof window.location!=="undefined"){var a=window.location.href;if(a&&/\bdebug=true\b/.test(a)){a=/\bdebugLevel=(\d+)/.exec(a);i.debug=a?+a[1]:3}}})();var O=u.Mark;i.invisibleFill="rgba(127,127,127,0.00001)"; -i.logSeparator="------------------------------------------";var Gb=Array.prototype.slice;i.setDebug=function(a){a=+a;i.debug=isNaN(a)?0:a;Ra();Sa();return i.debug};i.setDebug(i.debug);i.defaultCompatVersion=function(a){var b=i.BaseChart.prototype.defaults;if(a!=null)return b.compatVersion=a;return b.compatVersion};i.cloneMatrix=function(a){return a.map(function(b){return b.slice()})};i.stringify=function(a,b){var c=f.get(b,"maxLevel")||5,d=[];i.stringifyRecursive(d,a,c,b);return d.join("")};i.stringifyRecursive= -function(a,b,c,d){if(c>0){c--;switch(typeof b){case "undefined":return a.push("undefined");case "object":if(!b){a.push("null");return true}if(f.fun.is(b.stringify))return b.stringify(a,c,d);if(b instanceof Array){a.push("[");b.forEach(function(j,l){l&&a.push(", ");i.stringifyRecursive(a,j,c,d)||a.pop()});a.push("]")}else{var e=f.get(d,"ownOnly",true);if(b===f.global){a.push("");return true}if(f.fun.is(b.cloneNode)){a.push("");return true}if(c>1&&b.constructor!== -Object){c=1;e=true}a.push("{");var g=true;for(var h in b)if(!e||f.hasOwnProp.call(b,h)){g||a.push(", ");a.push(h+": ");if(i.stringifyRecursive(a,b[h],c,d)){if(g)g=false}else{a.pop();g||a.pop()}}if(g){b=""+b;b!=="[object Object]"&&a.push("{"+b+"}")}a.push("}")}return true;case "number":a.push(""+Math.round(1E5*b)/1E5);return true;case "boolean":a.push(""+b);return true;case "string":a.push(JSON.stringify(b));return true;case "function":if(f.get(d,"funs",false)){a.push(JSON.stringify(b.toString().substr(0, -13)+"..."));return true}return false}a.push("'new ???'");return true}};i.orientation={vertical:"vertical",horizontal:"horizontal"};i.extensionTag="extension";i.extendType=function(a,b,c){if(b){var d,e=a.prototype._vars,g=function(h,j){if(h!==undefined){d||(d={});if(e&&e[j])j="_"+j+"EvalCore";d[j]=f.fun.to(h)}};c?c.forEach(function(h){g(b[h],h)}):f.each(g);d&&a.add(d)}};u.Color.prototype.stringify=function(a,b,c){return i.stringifyRecursive(a,this.key,b,c)};O.prototype.hasDelegateValue=function(a, -b){var c=this.$propertiesMap[a];if(c)return!b||c.tag===b;if(this.proto)return this.proto.hasDelegateValue(a,b);return false};i.defaultColorScheme=null;i.brighterColorTransform=function(a){return(a.rgb?a:u.color(a)).brighter(0.6)};i.setDefaultColorScheme=function(a){return i.defaultColorScheme=i.colorScheme(a)};i.defaultColor=u.Colors.category10()("?");i.colorScheme=function(a){if(a==null)return null;if(typeof a==="function"){if(!a.hasOwnProperty("range"))return a;a=a.range()}else a=f.array.as(a); -if(!a.length)return null;return function(){var b=u.colors(a);b.domain.apply(b,arguments);return b}};i.createColorScheme=function(a){return i.colorScheme(a)||i.defaultColorScheme||u.Colors.category10};i.toGrayScale=function(a,b,c,d){a=u.color(a);var e=0.299*a.r+0.587*a.g+0.114*a.b;if(c===undefined)c=200;else if(c==null)c=255;if(d===undefined)d=30;else if(d==null)d=0;var g=c-d;e=g<=0?c:d+e/255*g;if(b==null)b=a.opacity;else if(b<0)b=-b*a.opacity;e=Math.round(e);return u.rgb(e,e,e,b)};i.removeTipsyLegends= -function(){try{$(".tipsy").remove()}catch(a){}};i.createDateComparer=function(a,b){if(!b)b=u.identity;return function(c,d){return a.parse(b(c))-a.parse(b(d))}};i.time={intervals:{y:31536E6,m:2592E6,d30:2592E6,w:6048E5,d7:6048E5,d:864E5,h:36E5,M:6E4,s:1E3,ms:1},withoutTime:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate())},weekday:{previousOrSelf:function(a,b){if(b=a.getDay()-b)a=new Date(a-(b<0?7+b:b)*i.time.intervals.d);return a},nextOrSelf:function(a,b){if(b=a.getDay()-b)a=new Date(a+ -(b>0?7-b:-b)*i.time.intervals.d);return a},closestOrSelf:function(a,b){if(b=a.getDay()-b){var c=i.time.intervals.d,d=b>0?1:-1;b=Math.abs(b);a=b>=4?new Date(a.getTime()+d*(7-b)*c):new Date(a.getTime()-d*b*c)}return a}}};u.Format.createParser=function(a){function b(c){return a.parse(c)}return b};u.Format.createFormatter=function(a){function b(c){return c!=null?a.format(c):""}return b};i.buildTitleFromName=function(a){return f.firstUpperCase(a).replace(/([a-z\d])([A-Z])/,"$1 $2")};i.buildIndexedId=function(a, -b){if(b>0)return a+""+(b+1);return a};i.splitIndexedId=function(a){a=/^(.*?)(\d*)$/.exec(a);var b=null;if(a[2]){b=Number(a[2]);if(b<=1)b=1;else b--}return[a[1],b]};var Hb=[null];i.makeExtensionAbsId=function(a,b){if(!a)return b;return f.query(b||Hb).selectMany(function(c){return f.query(a).select(function(d){return Ta(d,c)})}).where(f.truthy).array()};i.makeEnumParser=function(a,b,c){var d={};b.forEach(function(e){if(e)d[e.toLowerCase()]=e});if(c)c=c.toLowerCase();return function(e){if(e)e=(""+e).toLowerCase(); -if(!f.hasOwn(d,e)){e&&i.debug>=2&&i.log("[Warning] Invalid '"+a+"' value: '"+e+"'. Assuming '"+c+"'.");e=c}return e}};i.parseDistinctIndexArray=function(a,b,c){a=f.array.as(a);if(a==null)return null;if(b==null)b=0;if(c==null)c=Infinity;a=f.query(a).select(function(d){return+d}).where(function(d){return!isNaN(d)&&d>=b&&d<=c}).distinct().array();return a.length?a:null};i.parseLegendClickMode=i.makeEnumParser("legendClickMode",["toggleSelected","toggleVisible","none"],"toggleVisible");i.parseTooltipAutoContent= -i.makeEnumParser("tooltipAutoContent",["summary","value"],"value");i.parseSelectionMode=i.makeEnumParser("selectionMode",["rubberBand","focusWindow"],"rubberBand");i.parseClearSelectionMode=i.makeEnumParser("clearSelectionMode",["emptySpaceClick","manual"],"emptySpaceClick");i.parseShape=i.makeEnumParser("shape",["square","circle","diamond","triangle","cross","bar"],null);i.parseTreemapColorMode=i.makeEnumParser("colorMode",["byParent","bySelf"],"byParent");i.parseTreemapLayoutMode=i.makeEnumParser("layoutMode", -["squarify","slice-and-dice","slice","dice"],"squarify");i.parseContinuousColorScaleType=function(a){if(a){a=(""+a).toLowerCase();switch(a){case "linear":case "normal":case "discrete":break;default:i.debug>=2&&i.log("[Warning] Invalid 'ScaleType' option value: '"+a+"'.");a=null;break}}return a};i.parseDomainScope=function(a,b){if(a){a=(""+a).toLowerCase();switch(a){case "cell":case "global":break;case "section":if(!b)throw f.error.argumentRequired("orientation");a=b==="y"?"row":"column";break;case "column":case "row":if(b&& -b!==(a==="row"?"y":"x")){a="section";i.debug>=2&&i.log("[Warning] Invalid 'DomainScope' option value: '"+a+"' for the orientation: '"+b+"'.")}break;default:i.debug>=2&&i.log("[Warning] Invalid 'DomainScope' option value: '"+a+"'.");a=null;break}}return a};i.parseDomainRoundingMode=function(a){if(a){a=(""+a).toLowerCase();switch(a){case "none":case "nice":case "tick":break;default:i.debug>=2&&i.log("[Warning] Invalid 'DomainRoundMode' value: '"+a+"'.");a=null;break}}return a};i.parseOverlappedLabelsMode= -function(a){if(a){a=(""+a).toLowerCase();switch(a){case "leave":case "hide":case "rotatethenhide":break;default:i.debug>=2&&i.log("[Warning] Invalid 'OverlappedLabelsMode' option value: '"+a+"'.");a=null;break}}return a};i.castNumber=function(a){if(a!=null){a=+a;if(isNaN(a))a=null}return a};i.parseWaterDirection=function(a){if(a){a=(""+a).toLowerCase();switch(a){case "up":case "down":return a}i.debug>=2&&i.log("[Warning] Invalid 'WaterDirection' value: '"+a+"'.")}};i.parseTrendType=function(a){if(a){a= -(""+a).toLowerCase();if(a==="none")return a;if(i.trends.has(a))return a;i.debug>=2&&i.log("[Warning] Invalid 'TrendType' value: '"+a+"'.")}};i.parseNullInterpolationMode=function(a){if(a){a=(""+a).toLowerCase();switch(a){case "none":case "linear":case "zero":return a}i.debug>=2&&i.log("[Warning] Invalid 'NullInterpolationMode' value: '"+a+"'.")}};i.parseAlign=function(a,b){if(b)b=(""+b).toLowerCase();var c;if(a==="left"||a==="right"){a=b&&i.BasePanel.verticalAlign[b];if(!a){a="middle";c=!!b}}else{a= -b&&i.BasePanel.horizontalAlign[b];if(!a){a="center";c=!!b}}c&&i.debug>=2&&i.log(f.format("Invalid alignment value '{0}'. Assuming '{1}'.",[b,a]));return a};i.parseAnchor=function(a){if(a){a=(""+a).toLowerCase();switch(a){case "top":case "left":case "center":case "bottom":case "right":return a}i.debug>=2&&i.log(f.format("Invalid anchor value '{0}'.",[a]))}};i.parseAnchorWedge=function(a){if(a){a=(""+a).toLowerCase();switch(a){case "outer":case "inner":case "center":case "start":case "end":return a}i.debug>= -2&&i.log(f.format("Invalid wedge anchor value '{0}'.",[a]))}};i.unionExtents=function(a,b){if(a){if(b){if(b.mina.max)a.max=b.max}}else{if(!b)return null;a={min:b.min,max:b.max}}return a};var F=i.Sides=function(a){a!=null&&this.setSides(a)};F.hnames="left right".split(" ");F.vnames="top bottom".split(" ");F.names="left right top bottom".split(" ");F.namesSet=u.dict(F.names,f.retTrue);i.parsePosition=function(a,b){if(a){a=(""+a).toLowerCase();if(!f.hasOwn(F.namesSet,a)){var c= -b||"left";i.debug>=2&&i.log(f.format("Invalid position value '{0}. Assuming '{1}'.",[a,c]));a=c}}return a||b||"left"};F.as=function(a){if(a!=null&&!(a instanceof F))a=(new F).setSides(a);return a};F.prototype.stringify=function(a,b,c){return i.stringifyRecursive(a,f.copyOwn(this),b,c)};F.prototype.setSides=function(a){if(typeof a==="string"){var b=a.split(/\s+/).map(function(c){return L.parse(c)});switch(b.length){case 1:this.set("all",b[0]);return this;case 2:this.set("top",b[0]);this.set("left", -b[1]);this.set("right",b[1]);this.set("bottom",b[0]);return this;case 3:this.set("top",b[0]);this.set("left",b[1]);this.set("right",b[1]);this.set("bottom",b[2]);return this;case 4:this.set("top",b[0]);this.set("right",b[1]);this.set("bottom",b[2]);this.set("left",b[3]);return this;case 0:return this}}else if(typeof a==="number"){this.set("all",a);return this}else if(typeof a==="object"){if(a instanceof L)this.set("all",a);else{this.set("all",a.all);for(b in a)b!=="all"&&F.namesSet.hasOwnProperty(b)&& -this.set(b,a[b])}return this}i.debug&&i.log("Invalid 'sides' value: "+i.stringify(a));return this};F.prototype.set=function(a,b){b=L.parse(b);if(b!=null)if(a==="all")F.names.forEach(function(c){this[c]=b},this);else if(f.hasOwn(F.namesSet,a))this[a]=b};F.prototype.resolve=function(a,b){if(typeof a==="object"){b=a.height;a=a.width}var c={};F.names.forEach(function(d){var e=0,g=this[d];if(g!=null)e=typeof g==="number"?g:g.resolve(d==="left"||d==="right"?a:b);c[d]=e},this);return F.updateSize(c)};F.updateSize= -function(a){a.width=(a.left||0)+(a.right||0);a.height=(a.bottom||0)+(a.top||0);return a};F.resolvedMax=function(a,b){var c={};F.names.forEach(function(d){c[d]=Math.max(a[d]||0,b[d]||0)});return c};F.inflate=function(a,b){var c={};F.names.forEach(function(d){c[d]=(a[d]||0)+b});return F.updateSize(c)};var L=i.PercentValue=function(a){this.percent=a};L.prototype.resolve=function(a){return this.percent*a};L.parse=function(a){if(a!=null&&a!==""){switch(typeof a){case "number":return a;case "string":var b= -a.match(/^(.+?)\s*(%)?$/);if(b){var c=+b[1];if(!isNaN(c))if(b[2]){if(c>=0)return new L(c/100)}else return c}break;case "object":if(a instanceof L)return a;break}i.debug&&i.log(f.format("Invalid margins component '{0}'",[""+a]))}};L.resolve=function(a,b){return a instanceof L?a.resolve(b):a};var Ib=O.prototype.renderCore,Qa=O.prototype.zOrder;O.prototype.zOrder=function(a){var b=this.borderPanel;if(b&&b!==this)return Qa.call(b,a);return Qa.call(this,a)};O.prototype.renderCore=function(){var a=this.root; -a._renderId=(a._renderId||0)+1;i.debug>=25&&i.log("BEGIN RENDER "+a._renderId);Ib.call(this);i.debug>=25&&i.log("END RENDER "+a._renderId)};O.prototype.renderId=function(){return this.root._renderId};O.prototype.wrapper=function(a){this._wrapper=a;return this};O.prototype.wrap=function(a,b){if(a&&f.fun.is(a)&&this._wrapper&&!a._cccWrapped){a=this._wrapper(a,b);a._cccWrapped=true}return a};O.prototype.lock=function(a,b){b!==undefined&&this[a](b);(this._locked||(this._locked={}))[a]=true;return this}; -O.prototype.isIntercepted=function(a){return this._intercepted&&this._intercepted[a]};O.prototype.isLocked=function(a){return this._locked&&this._locked[a]};O.prototype.ensureEvents=function(a){var b=this.propertyValue("events",true);if(!b||b==="none")this.events(a||"all");return this};O.prototype.addMargin=function(a,b){if(b!==0){var c=f.nullyTo(this.propertyValue(a),0),d=u.functor(c);this[a](function(){return b+d.apply(this,Gb.call(arguments))})}return this};O.prototype.addMargins=function(a){var b= -f.get(a,"all",0);this.addMargin("left",f.get(a,"left",b));this.addMargin("right",f.get(a,"right",b));this.addMargin("top",f.get(a,"top",b));this.addMargin("bottom",f.get(a,"bottom",b));return this};O.prototype.eachInstanceWithData=function(a,b){this.eachInstance(function(c,d,e){c.mark.sign&&c[d].data&&a.call(b,c,d,e)})};O.prototype.eachSceneWithDataOnRect=function(a,b,c,d){function e(l,m){if(l.intersectsRect(a))(l=m.data)&&l.datum&&b.call(c,l)}var g=this,h=g.sign;if(!(h&&!h.selectable())){if(d==null)d= -g.rubberBandSelectionMode||"partial";var j=d==="center";g.eachInstanceWithData(function(l,m,k){var n=g.getShape(l,m,0.15);n=(j?n.center():n).apply(k);e(n,l[m],m)})}};O.prototype.eachDatumOnRect=function(a,b,c,d){function e(l,m){if(l.intersectsRect(a))(l=m.data)&&l.datum&&l.datums().each(function(k){k.isNull||b.call(c,k)})}var g=this,h=g.sign;if(!(h&&!h.selectable())){if(d==null)d=g.rubberBandSelectionMode||"partial";var j=d==="center";g.eachInstanceWithData(function(l,m,k){var n=g.getShape(l,m,0.15); -n=(j?n.center():n).apply(k);e(n,l[m],m)})}};u.Transform.prototype.transformHPosition=function(a){return this.x+this.k*a};u.Transform.prototype.transformVPosition=function(a){return this.y+this.k*a};u.Transform.prototype.transformLength=function(a){return this.k*a};var M=f.type("pvc.Size").init(function(a,b){if(arguments.length===1)a!=null&&this.setSize(a);else{if(a!=null)this.width=a;if(b!=null)this.height=b}}).add({stringify:function(a,b,c){return i.stringifyRecursive(a,f.copyOwn(this),b,c)},setSize:function(a, -b){if(typeof a==="string"){var c=a.split(/\s+/).map(function(d){return L.parse(d)});switch(c.length){case 1:this.set(f.get(b,"singleProp","all"),c[0]);return this;case 2:this.set("width",c[0]);this.set("height",c[1]);return this;case 0:return this}}else if(typeof a==="number"){this.set(f.get(b,"singleProp","all"),a);return this}else if(typeof a==="object"){if(a instanceof L)this.set(f.get(b,"singleProp","all"),a);else{this.set("all",a.all);for(c in a)c!=="all"&&this.set(c,a[c])}return this}i.debug&& -i.log("Invalid 'size' value: "+i.stringify(a));return this},set:function(a,b){if(b!=null&&(a==="all"||f.hasOwn(M.namesSet,a))){b=L.parse(b);if(b!=null)if(a==="all")M.names.forEach(function(c){this[c]=b},this);else this[a]=b}return this},clone:function(){return new M(this.width,this.height)},intersect:function(a){return new M(Math.min(this.width,a.width),Math.min(this.height,a.height))},resolve:function(a){var b={};M.names.forEach(function(c){var d=this[c];if(d!=null)if(typeof d==="number")b[c]=d; -else if(a){var e=a[c];if(e!=null)b[c]=d.resolve(e)}},this);return b}});M.names=["width","height"];M.namesSet=u.dict(M.names,f.retTrue);M.toOrtho=function(a,b){if(a!=null){var c;if(b)c=i.BasePanel.orthogonalLength[b];a=M.to(a,{singleProp:c});b&&delete a[i.BasePanel.oppositeLength[c]]}return a};M.to=function(a,b){if(a!=null&&!(a instanceof M))a=(new M).setSize(a,b);return a};var X=f.type("pvc.Offset").init(function(a,b){if(arguments.length===1)a!=null&&this.setOffset(a);else{if(a!=null)this.x=a;if(b!= -null)this.y=b}}).add({stringify:function(a,b,c){return i.stringifyRecursive(a,f.copyOwn(this),b,c)},setOffset:function(a,b){if(typeof a==="string"){var c=a.split(/\s+/).map(function(d){return L.parse(d)});switch(c.length){case 1:this.set(f.get(b,"singleProp","all"),c[0]);return this;case 2:this.set("x",c[0]);this.set("y",c[1]);return this;case 0:return this}}else if(typeof a==="number"){this.set(f.get(b,"singleProp","all"),a);return this}else if(typeof a==="object"){this.set("all",a.all);for(c in a)c!== -"all"&&this.set(c,a[c]);return this}i.debug&&i.log("Invalid 'offset' value: "+i.stringify(a));return this},set:function(a,b){if(b!=null&&f.hasOwn(X.namesSet,a)){b=L.parse(b);if(b!=null)if(a==="all")X.names.forEach(function(c){this[c]=b},this);else this[a]=b}},resolve:function(a){var b={};M.names.forEach(function(c){var d=X.namesSizeToOffset[c],e=this[d];if(e!=null)if(typeof e==="number")b[d]=e;else if(a){c=a[c];if(c!=null)b[d]=e.resolve(c)}},this);return b}});X.addStatic({names:["x","y"]}).addStatic({namesSet:u.dict(X.names, -f.retTrue),namesSizeToOffset:{width:"x",height:"y"},namesSidesToOffset:{left:"x",right:"x",top:"y",bottom:"y"},as:function(a){if(a!=null&&!(a instanceof X))a=(new X).setOffset(a);return a}});(function(){jQuery.support.svg=jQuery.support.svg||document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")})(jQuery);i.text={getFitInfo:function(a,b,c,d,e){if(c==="")return{h:true,v:true,d:true};c=u.Text.measure(c,d).width;return{h:c<=a,v:c<=b,d:c<=Math.sqrt(a*a+b*b)-e}}, -trimToWidthB:function(a,b,c,d,e){a-=u.Text.measure(d,c).width;return i.text.trimToWidth(a,b,c,d,e)},trimToWidth:function(a,b,c,d,e){if(b==="")return b;var g=u.Text.measure(b,c).width;if(g<=a)return b;if(g>a*1.5)return i.text.trimToWidthBin(a,b,c,d,e);for(;g>a;){b=e?b.slice(1):b.slice(0,b.length-1);g=u.Text.measure(b,c).width}return e?d+b:b+d},trimToWidthBin:function(a,b,c,d,e){for(var g=b.length,h=g-2,j=0,l,m;j<=h&&h>0;){l=Math.ceil((j+h)/2);var k=e?b.slice(g-l):b.slice(0,l);m=u.Text.measure(k,c).width; -if(m>a)h=l-1;else if(u.Text.measure(e?b.slice(g-l-1):b.slice(0,l+1),c).widthb){e&&d.push(e);e=g}else e=h}}e&&d.push(e);return d},getLabelBBox:function(a,b,c,d,e,g){b=u.Label.getPolygon(a,b,c,d,e,g);d=b.bbox();d.source=b;d.sourceAngle=e;d.sourceAlign= -c;d.sourceTextWidth=a;return d}};i.color={scale:ya,scales:xa,toGray:i.toGrayScale,isGray:wa};f.type("pvc.color.ScalesBuild").init(function(a){this.keyArgs=a;this.data=a.data||f.fail.argumentRequired("keyArgs.data");this.domainDimName=a.colorDimension||f.fail.argumentRequired("keyArgs.colorDimension");this.domainDim=this.data.dimensions(this.domainDimName);var b=this.domainDim.type;if(b.isComparable)this.domainComparer=function(c,d){return b.compare(c,d)};else{this.domainComparer=null;i.log("Color value dimension should be comparable. Generated color scale may be invalid.")}this.nullRangeValue= -a.colorMissing?u.color(a.colorMissing):u.Color.transparent;this.domainRangeCountDif=0}).add({build:function(){this.range=this._getRange();this.desiredDomainCount=this.range.length+this.domainRangeCountDif;return this._createScale(this._getDomain())},buildMap:function(){this.range=this._getRange();this.desiredDomainCount=this.range.length+this.domainRangeCountDif;var a;if(this.keyArgs.normPerBaseCategory)a=function(b){return this._createScale(this._ensureDomain(null,false,b))};else{a=this._createScale(this._getDomain()); -a=f.fun.constant(a)}return this._createCategoryScalesMap(a)},_createScale:f.method({isAbstract:true}),_createCategoryScalesMap:function(a){return this.data.children().object({name:function(b){return b.absKey},value:a,context:this})},_getRange:function(){var a=this.keyArgs,b=a.colors||["red","yellow","green"];if(a.colorMin!=null&&a.colorMax!=null)b=[a.colorMin,a.colorMax];else if(a.colorMin!=null)b.unshift(a.colorMin);else a.colorMax!=null&&b.push(a.colorMax);return b.map(function(c){return u.color(c)})}, -_getDataExtent:function(a){var b=a.dimensions(this.domainDimName).extent({visible:true});if(!b)return null;a=b.min.value;b=b.max.value;if(b==a)if(b>=1)a=b-1;else b=a+1;return{min:a,max:b}},_getDomain:function(){var a=this.keyArgs.colorDomain;if(a!=null){this.domainComparer&&a.sort(this.domainComparer);if(a.length>this.desiredDomainCount)a=a.slice(0,this.desiredDomainCount)}else a=[];return this._ensureDomain(a,true,this.data)},_ensureDomain:function(a,b,c){var d;if(a&&b){b=this.desiredDomainCount- -a.length;if(b>0)if(d=this._getDataExtent(c))switch(b){case 1:this.domainComparer?f.array.insert(a,d.max,this.domainComparer):a.push(d.max);break;case 2:if(this.domainComparer){f.array.insert(a,d.min,this.domainComparer);f.array.insert(a,d.max,this.domainComparer)}else{a.unshift(d.min);a.push(d.max)}break;default:i.debug>=2&&i.log("Ignoring option 'colorDomain' due to unsupported length."+f.format(" Should have '{0}', but instead has '{1}'.",[this.desiredDomainCount,a.length]));a=null}}if(!a){d||(d= -this._getDataExtent(c));if(d){a=d.min;d=d.max;c=(d-a)/(this.desiredDomainCount-1);a=u.range(a,d+c,c)}}return a}});f.type("pvc.color.LinearScalesBuild",i.color.ScalesBuild).add({_createScale:function(a){var b=u.Scale.linear();a&&b.domain.apply(b,a);b.range.apply(b,this.range);return b}});f.type("pvc.color.DiscreteScalesBuild",i.color.ScalesBuild).init(function(a){this.base(a);this.domainRangeCountDif=1}).add({_createScale:function(a){function b(h){if(h==null)return e;for(var j=0;j=2&&f.hasOwn(b,c)&&i.log(f.format("[WARNING] A trend type with the name '{0}' is already defined.", -[c]));var e=d.label||f.fail.argumentRequired("trendSpec.label");d=d.model||f.fail.argumentRequired("trendSpec.model");f.fun.is(d)||f.fail.argumentInvalid("trendSpec.mode","Must be a function.");b[c]={dataPartAtom:{v:"trend",f:e},type:c,label:e,model:d}},"get",function(c){c||f.fail.argumentRequired("type");return f.getOwn(b,c)||f.fail.operationInvalid("Undefined trend type '{0}'.",[c])},"has",function(c){return f.hasOwn(b,c)},"types",function(){return f.ownKeys(b)});a.define("linear",{label:"Linear trend", -model:function(c){for(var d=f.get(c,"rows"),e=f.get(c,"x"),g=f.get(c,"y"),h=0,j=c=0,l=0,m=0,k=0,n=function(r){return r!=null?+r:NaN};d.next();){var o=d.item,p=e?n(e(o)):h;if(!isNaN(p)){o=n(g(o));if(!isNaN(o)){c++;j+=p;l+=o;m+=p*o;k+=p*p}}h++}var q,s;if(c>=2){d=j/c;e=l/c;m=m/c;c=k/c-d*d;s=c===0?0:(m-d*e)/c;q=e-s*d;return{alpha:q,beta:s,reset:f.noop,sample:function(r){return q+s*+r}}}}});a.define("moving-average",{label:"Moving average",model:function(c){var d=Math.max(+(f.get(c,"periods")||3),2),e= -0,g=[];return{reset:function(){e=0;g.length=0},sample:function(h,j){h=d;if(j!=null){g.unshift(j);e+=j;h=g.length;if(h>d){e-=g.pop();h=d}}return e/h}}}});a.define("weighted-moving-average",{label:"Weighted Moving average",model:function(c){var d=Math.max(+(f.get(c,"periods")||3),2),e=0,g=0,h=[],j=0,l=0;return{reset:function(){e=g=l=j=0;h.length=0},sample:function(m,k){if(k!=null)if(j=0)this.label=f.format(this.label,[this.groupLevel+1]);this.playedVisualRoles=new f.Map;this.isHidden=!!f.get(c,"isHidden");a=f.get(c,"valueType")||null;b=i.data.DimensionType.valueTypeName(a);var d=f.getOwn(i.data.DimensionType.cast,b,null);this.valueType=a;this.valueTypeName= -b;this.cast=d;this.isDiscreteValueType=this.valueType!==Number&&this.valueType!==Date;this.isDiscrete=f.get(c,"isDiscrete");if(this.isDiscrete==null)this.isDiscrete=this.isDiscreteValueType;else{this.isDiscrete=!!this.isDiscrete;if(!this.isDiscrete&&this.isDiscreteValueType)throw f.error.argumentInvalid("isDiscrete","The only supported continuous value types are Number and Date.");}this._converter=f.get(c,"converter")||null;if(!this._converter)if(a=f.get(c,"rawFormat"))switch(this.valueType){case Date:this._converter= -u.Format.createParser(u.Format.date(a));break}this._key=f.get(c,"key")||null;this._comparer=f.get(c,"comparer");if(this._comparer===undefined)switch(this.valueType){case Number:case Date:this._comparer=f.compare;break;default:this._comparer=null}this.isComparable=this._comparer!=null;this._formatter=f.get(c,"formatter")||null;if(!this._formatter)switch(this.valueType){case Number:this._formatter=u.Format.createFormatter(u.Format.number().fractionDigits(0,2));break;case Date:a=f.get(c,"format");if(!a)if(a= -f.get(c,"rawFormat"))a=a.replace(/-/g,"/");a||(a="%Y/%m/%d");this._formatter=u.Format.createFormatter(u.Format.date(a));break}}).add({isCalculated:false,compare:function(a,b){if(a==null){if(b==null)return 0;return-1}else if(b==null)return 1;return this._comparer.call(null,a,b)},comparer:function(a){if(!this.isComparable)return null;var b=this;if(a)return this._reverseComparer||(this._reverseComparer=function(c,d){return b.compare(d,c)});return this._directComparer||(this._directComparer=function(c, -d){return b.compare(c,d)})},atomComparer:function(a){if(a)return this._reverseAtomComparer||(this._reverseAtomComparer=this._createReverseAtomComparer());return this._directAtomComparer||(this._directAtomComparer=this._createDirectAtomComparer())},_toDiscrete:function(){this.isDiscrete=true},_toCalculated:function(){this.isCalculated=true},_createReverseAtomComparer:function(){function a(c,d){if(c===d)return 0;return b.compare(d.value,c.value)}if(!this.isComparable)return cb;var b=this;return a}, -_createDirectAtomComparer:function(){function a(c,d){if(c===d)return 0;return b.compare(c.value,d.value)}if(!this.isComparable)return bb;var b=this;return a},formatter:function(){return this._formatter},converter:function(){return this._converter},playingPercentVisualRole:function(){return f.query(this.playedVisualRoles.values()).any(function(a){return a.isPercent})}});i.data.DimensionType.cast={Date:function(a){return a instanceof Date?a:new Date(a)},Number:function(a){a=Number(a);return isNaN(a)? -null:a},String:String,Boolean:Boolean,Object:Object,Any:null};i.data.DimensionType.dimensionGroupName=function(a){return a.replace(/^(.*?)(\d*)$/,"$1")};i.data.DimensionType.valueTypeName=function(a){if(a==null)return"Any";switch(a){case Boolean:return"Boolean";case Number:return"Number";case String:return"String";case Object:return"Object";case Date:return"Date";default:throw f.error.argumentInvalid("valueType","Invalid valueType function: '{0}'.",[a]);}};i.data.DimensionType.extendSpec=function(a, -b,c){a=i.data.DimensionType.dimensionGroupName(a);var d=f.get(c,"dimensionGroups");if(d)if(d=d[a])b=f.create(d,b);b||(b={});switch(a){case "category":if(f.get(c,"isCategoryTimeSeries",false))if(b.valueType===undefined)b.valueType=Date;break;case "value":if(b.valueType===undefined)b.valueType=Number;if(b.valueType===Number)if(b.formatter===undefined&&!b.format)b.formatter=f.get(c,"valueNumberFormatter");break}if(b.converter===undefined&&b.valueType===Date&&!b.rawFormat)b.rawFormat=f.get(c,"timeSeriesFormat"); -return b};f.type("pvc.data.ComplexType").init(function(a){this._dims={};this._dimsList=[];this._dimsNames=[];this._calculations=[];this._calculatedDimNames={};this._dimsIndexByName=null;this._dimsByGroup={};this._dimsNamesByGroup={};if(a)for(var b in a)this.addDimension(b,a[b])}).add({describe:function(){var a=["COMPLEX TYPE INFORMATION",i.logSeparator];this._dimsList.forEach(function(b){var c=[];c.push(b.valueTypeName);b.isComparable&&c.push("comparable");b.isDiscrete||c.push("continuous");b.isHidden&& -c.push("hidden");a.push(" "+b.name+" ("+c.join(", ")+")")});return a.join("\n")},dimensions:function(a,b){if(a==null)return this._dims;var c=f.getOwn(this._dims,a,null);if(!c&&f.get(b,"assertExists",true))throw f.error.argumentInvalid("name","Undefined dimension '{0}'",[a]);return c},dimensionsList:function(){return this._dimsList},calculatedDimensionsList:function(){return this._calcDimsList},dimensionsNames:function(){return this._dimsNames},groupDimensions:function(a,b){var c=f.getOwn(this._dimsByGroup, -a);if(!c&&f.get(b,"assertExists",true))throw f.error.operationInvalid("There is no dimension type group with name '{0}'.",[a]);return c},groupDimensionsNames:function(a,b){var c=f.getOwn(this._dimsNamesByGroup,a);if(!c&&f.get(b,"assertExists",true))throw f.error.operationInvalid("There is no dimension type group with name '{0}'.",[a]);return c},addDimension:function(a,b){a||f.fail.argumentRequired("name");!f.hasOwn(this._dims,a)||f.fail.operationInvalid("A dimension type with name '{0}' is already defined.", -[a]);b=new i.data.DimensionType(this,a,b);this._dims[a]=b;this._dimsIndexByName=null;var c=b.group,d;if(c){var e=f.getOwn(this._dimsByGroup,c);if(e)d=this._dimsNamesByGroup[c];else{e=this._dimsByGroup[c]=[];d=this._dimsNamesByGroup[c]=[]}d=f.array.insert(d,a,f.compare);d=~d;f.array.insertAt(e,d,b)}var g;e=this._dimsList.length;if(c){d=b.groupLevel;for(var h=0;hd){g=h;break}g=h+1}}if(g==null)g=e}else g=e;f.array.insertAt(this._dimsList, -g,b);f.array.insertAt(this._dimsNames,g,a);if(b._calculate){g=f.array.binarySearch(this._calcDimsList,b._calculationOrder,f.compare,function(l){return l._calculationOrder});if(g>=0)g++;else g=~g;f.array.insertAt(this._calcDimsList,g,b)}this._isPctRoleDimTypeMap=null;return b},addCalculation:function(a,b){a||f.fail.argumentRequired("calcSpec");var c=a.calculation||f.fail.argumentRequired("calculations[i].calculation");a=a.names;if((a=typeof a==="string"?a.split(/\s*\,\s*/):f.array.as(a))&&a.length){var d= -this._calculatedDimNames;a.forEach(function(e){if(e){e=e.replace(/^\s*(.+?)\s*$/,"$1");!f.hasOwn(d,e)||f.fail.argumentInvalid("calculations[i].names","Dimension name '{0}' is already being calculated.",[e]);var g=this._dims[e];if(!g){var h=i.data.DimensionType.extendSpec(e,null,b);this.addDimension(e,h)}d[e]=true;g._toCalculated()}},this)}this._calculations.push(c)},isCalculated:function(a){return f.hasOwn(this._calculatedDimNames,a)},_calculate:function(a){var b=this._calculations;if(b.length){var c= -{};b.forEach(function(d){d(a,c)});return c}},getPlayingPercentVisualRoleDimensionMap:function(){var a=this._isPctRoleDimTypeMap;if(!a)a=this._isPctRoleDimTypeMap=new f.Map(f.query(f.own(this._dims)).where(function(b){return b.playingPercentVisualRole()}).object({name:function(b){return b.name}}));return a},sortDimensionNames:function(a,b){var c=this._dimsIndexByName;if(!c)this._dimsIndexByName=c=f.query(this._dimsList).object({name:function(d){return d.name},value:function(d,e){return e}});a.sort(function(d, -e){return f.compare(c[b?b(d):d],c[b?b(e):e])});return a}});f.type("pvc.data.ComplexTypeProject").init(function(a){this._dims={};this._dimList=[];this._dimGroupsDims={};this._dimGroupSpecs=a||{};this._calcList=[]}).add({_ensureDim:function(a,b){a||f.fail.argumentInvalid("name","Invalid dimension name '{0}'.",[a]);var c=f.getOwn(this._dims,a);if(c)b&&f.setUDefaults(c.spec,b);else{c=this._dims[a]=this._createDim(a,b);this._dimList.push(c);b=f.array.lazy(this._dimGroupsDims,c.groupName);f.array.insert(b, -a,f.compare)}return c},hasDim:function(a){return f.hasOwn(this._dims,a)},setDim:function(a,b){a=this._ensureDim(a).spec;b&&f.copy(a,b);return this},setDimDefaults:function(a,b){f.setUDefaults(this._ensureDim(a).spec,b);return this},_createDim:function(a,b){var c=i.data.DimensionType.dimensionGroupName(a),d=this._dimGroupSpecs[c];if(d)b=f.create(d,b);return{name:a,groupName:c,spec:b||{}}},readDim:function(a,b){b=this._ensureDim(a,b);if(b.isRead)throw f.error.operationInvalid("Dimension '{0}' already is the target of a reader.", -[a]);if(b.isCalc)throw f.error.operationInvalid("Dimension '{0}' is being calculated, so it cannot be the target of a reader.",[a]);b.isRead=true},calcDim:function(a,b){b=this._ensureDim(a,b);if(b.isCalc)throw f.error.operationInvalid("Dimension '{0}' already is being calculated.",[a]);if(b.isRead)throw f.error.operationInvalid("Dimension '{0}' is the target of a reader, so it cannot be calculated.",[a]);b.isCalc=true},isReadOrCalc:function(a){if(a)if(a=f.getOwn(this._dims,a))return a.isRead||a.isCalc; -return false},groupDimensionsNames:function(a){return this._dimGroupsDims[a]},setCalc:function(a){a||f.fail.argumentRequired("calculations[i]");a.calculation||f.fail.argumentRequired("calculations[i].calculation");var b=a.names;(b=typeof b==="string"?b.split(/\s*\,\s*/):f.array.as(b))&&b.length&&b.forEach(this.calcDim,this);this._calcList.push(a)},configureComplexType:function(a,b){this._dimList.forEach(function(c){var d=c.name;c=c.spec;c=i.data.DimensionType.extendSpec(d,c,b);a.addDimension(d,c)}); -this._calcList.forEach(function(c){a.addCalculation(c)})}});f.type("pvc.data.TranslationOper").init(function(a,b,c,d,e){this.chart=a;this.complexTypeProj=b;this.source=c;this.metadata=d||{};this.options=e||{};this._initType();if(i.debug>=4){this._logItems=true;this._logItemCount=0}}).add({_logItems:false,logSource:f.method({isAbstract:true}),logVItem:f.method({isAbstract:true}),_translType:"Unknown",logTranslatorType:function(){return this._translType+" data source translator"},virtualItemSize:function(){return this.metadata.length}, -freeVirtualItemSize:function(){return this.virtualItemSize()-this._userUsedIndexesCount},setSource:function(a){if(!a)throw f.error.argumentRequired("source");this.source=a},defReader:function(a){a||f.fail.argumentRequired("readerSpec");var b;b=f.string.is(a)?a:a.names;b=f.string.is(b)?b.split(/\s*\,\s*/):f.array.as(b);var c=f.array.as(a.indexes);c&&c.forEach(this._userUseIndex,this);var d=!!(b&&b.length);if(a=a.reader){d||f.fail.argumentRequired("reader.names","Required argument when a reader function is specified."); -this._userRead(a,b)}else{if(d)return this._userCreateReaders(b,c);c&&c.forEach(function(e){this._userIndexesToSingleDim[e]=null},this)}return c},configureType:function(){this._configureTypeCore()},_configureTypeCore:f.method({isAbstract:true}),_initType:function(){this._userDimsReaders=[];this._userDimsReadersByDim={};this._userItem=[];this._userUsedIndexes={};this._userUsedIndexesCount=0;this._userIndexesToSingleDim=[];var a=this.options.readers;a&&a.forEach(this.defReader,this);if(a=i.parseDistinctIndexArray(this.options.multiChartIndexes))this._multiChartIndexes= -this.defReader({names:"multiChart",indexes:a})},_userUseIndex:function(a){a=+a;if(a<0)throw f.error.argumentInvalid("index","Invalid reader index: '{0}'.",[a]);if(f.hasOwn(this._userUsedIndexes,a))throw f.error.argumentInvalid("index","Virtual item index '{0}' is already assigned.",[a]);this._userUsedIndexes[a]=true;this._userUsedIndexesCount++;this._userItem[a]=true;return a},_userCreateReaders:function(a,b){if(b)b.forEach(function(l,m){b[m]=+l});else b=[];var c=b.length,d=a.length,e;if(d>c){e=c> -0?b[c-1]+1:0;do{e=this._nextAvailableItemIndex(e);b[c]=e;this._userUseIndex(e);c++}while(d>c)}for(var g=c===d?d:d-1,h,j=0;j=0)if((c=this._itemInfos[c])&&!this.options.ignoreMetadataLabels)if(c=c.label||c.name)d={label:c};this.complexTypeProj.readDim(a,d);this._userDimsReadersByDim[a]=b},execute:function(a){this.data=a;return this._executeCore()},_executeCore:function(){var a=this._getDimensionsReaders();return f.query(this._getItems()).select(function(b){return this._readItem(b, -a)},this)},_getItems:function(){return this.source},_getDimensionsReaders:function(){return this._userDimsReaders},_readItem:function(a,b){var c=this._logItems;if(c)if(this._logItemCount<10){i.log("virtual item ["+this._logItemCount+"]: "+i.stringify(a));this._logItemCount++}else{i.log("...");c=this._logItems=false}for(var d=0,e=b.length,g=this.data,h={};d read: "+i.stringify(a))}return h}, -_propGet:function(a,b){function c(d,e){e[a]=d[b]}return c},_nextAvailableItemIndex:function(a,b){if(a==null)a=0;if(b==null)b=Infinity;for(;a0;h++)for(var j=e[h],l=0;l10&&a.push(" ...");a.push("COLS ("+this.J+")");var b=this._columnTypes;this.metadata.forEach(function(c,d){a.push(" ["+d+"] '"+c.colName+"' (type: "+c.colType+ -", inspected: "+(b[d]?"number":"string")+(c.colLabel?", label: '"+c.colLabel+"'":"")+")")});a.push("");return a.join("\n")},_logVItem:function(a,b){var c=["VIRTUAL ITEM ARRAY",i.logSeparator],d=4,e=5,g=9;this._itemInfos.forEach(function(j,l){d=Math.max(d,(j.name||"").length);e=Math.max(e,(j.label||"").length);if(j=this._userIndexesToSingleDim[l])g=Math.max(g,j.length)},this);c.push("Index | Kind | Type | "+f.string.padRight("Name",d)+" | "+f.string.padRight("Label",e)+" > Dimension","------+------+--------+-"+ -f.string.padRight("",d,"-")+"-+-"+f.string.padRight("",e,"-")+"-+-"+f.string.padRight("",g,"-")+"-");var h=0;a.forEach(function(j){for(var l=0,m=b[j];l=d)throw f.error.argumentInvalid("plot2DataSeriesIndexes","Index is out of range '{0}'.",[g]);c||(c={});c[b[g]]=true});return c},_dataPartGet:function(a,b){function c(k,n){if(!g){h=a();g=d.data.dimensions(e);i.debug>=3&&h&&i.log("Second axis series values: "+i.stringify(f.keys(h)))}b(k, -m);k=m.series;if(k!=null&&k.v!=null)k=k.v;k=f.hasOwn(h,k)?l||(l=g.intern("1")):j||(j=g.intern("0"));n[e]=k}var d=this,e=this.options.dataPartDimName,g,h,j,l,m={};return c}});f.type("pvc.data.CrosstabTranslationOper",i.data.MatrixTranslationOper).add({_translType:"Crosstab",virtualItemSize:function(){return this.R+this.C+this.M},_executeCore:function(){function a(j,l){var m=g[j],k=0;for(j=h[j];j-- >0;)e[m++]=l[k++]}function b(j,l){var m=g.M;l=h._colGroupsIndexes[l];for(var k=h.M,n=0;n0){if(d){this.measuresDirection="columns";this._processEncodedColGroups(b)}else{this._colGroups= -b;this._colGroupsIndexes=[];this._colGroups.forEach(function(g,h){this._colGroups[h]=this._splitEncodedColGroupCell(g);this._colGroupsIndexes[h]=[this.R+h]},this);c.M=[this._buildItemInfoFromMetadata(a)]}this.C=this._colGroups[0].length;c.C=f.range(0,this.C).select(function(){return{type:0}}).array()}else{this.C=this.M=0;c.M=[];c.C=[]}}else{this.measuresDirection="rows";this.R=+this.options.measuresIndex;d=this.options.measuresCount;if(d==null)d=1;this.M=d;this._colGroups=b.slice(this.R+1);this._colGroups.forEach(function(g, -h){this._colGroups[h]=[g]},this)}}else{a=this.R=this._getCategoriesCount();this._colGroups=b.slice(a);this._colGroupsIndexes=new Array(this._colGroups.length);this._colGroups.forEach(function(g,h){this._colGroups[h]=[g];this._colGroupsIndexes[h]=[a+h]},this);c.C=[{type:0}];c.M=[{type:this._columnTypes[a]}]}c.R=f.range(0,this.R).select(this._buildItemInfoFromMetadata,this).array();b=this.options.seriesInRows;d=this._itemCrossGroupIndex={C:!b?0:this.R,R:!b?this.C:0,M:this.C+this.R};var e=this._itemInfos= -new Array(this.virtualItemSize());f.eachOwn(d,function(g,h){c[h].forEach(function(j,l){e[g+l]=j})});this._itemLogicalGroup={series:b?this.R:this.C,category:b?this.C:this.R,value:this.M};this._itemLogicalGroupIndex={series:0,category:this._itemLogicalGroup.series,value:this.C+this.R}},logVItem:function(){return this._logVItem(["C","R","M"],{C:this.C,R:this.R,M:this.M})},_getCategoriesCount:function(){var a=this.options.categoriesCount;if(a!=null&&(!isFinite(a)||a<0))a=null;if(a==null)(a=f.query(this._columnTypes).whayl(function(b){return b=== -0}).count())||(a=1);return a},_splitEncodedColGroupCell:function(a){var b=a.v,c;if(b==null)b=[];else{b=b.split(this._separator);if(c=a.f)c=c.split(this._separator)}return b.map(function(d,e){return{v:d,f:c&&c[e]}})},_processEncodedColGroups:function(a){for(var b=a.length||f.assert("Must have columns"),c=this.R,d=[],e,g={},h=[],j=0;jk.groupIndex)k.groupIndex=m}else{g[l]=k={name:l,label:o,type:this._columnTypes[c+j],groupIndex:m,index:j};h.push(k)}}h.sort(function(A,x){return f.compare(A.groupIndex,x.groupIndex)||f.compare(A.index,x.index)});h.forEach(function(A,x){A.groupIndex=x}); -a=d.length;var s=new Array(a),r=new Array(a),t=h.length;d.map(function(A,x){s[x]=A.values;var v=A.startIndex,y=r[x]=new Array(t);A.measureNames.forEach(function(z,w){y[g[z].groupIndex]=c+v+w})});this._colGroups=s;this._colGroupsIndexes=r;this._itemCrossGroupInfos.M=h;this.M=t},configureType:function(){if(this.measuresDirection==="rows")throw f.error.notImplemented();this.base()},_configureTypeCore:function(){function a(m,k,n){for(var o=d[m]+n;n>0;){var p=i.buildIndexedId(m,k);if(!b.complexTypeProj.isReadOrCalc(p)){e= -b._nextAvailableItemIndex(e);if(e>=o)return;g.push({names:p,indexes:e});e++;n--}k++}}var b=this,c=b._itemLogicalGroup,d=b._itemLogicalGroupIndex,e=0,g=[],h=this.options.dataPartDimName;if(h&&this.C===1&&!this.complexTypeProj.isReadOrCalc(h)){var j=this.options.plot2DataSeriesIndexes;if(j!=null){var l=this._colGroups.map(function(m){return""+m[0].v});this._plot2SeriesKeySet=this._createPlot2SeriesKeySet(j,l)}}["series","category","value"].forEach(function(m){var k=c[m];k>0&&a(m,0,k)});g&&g.forEach(this.defReader, -this);if(this._plot2SeriesKeySet)(j=this._userDimsReadersByDim.series)&&this._userRead(this._dataPartGet(f.fun.constant(this._plot2SeriesKeySet),j),h)}});f.type("pvc.data.RelationalTranslationOper",i.data.MatrixTranslationOper).add({M:0,C:0,S:0,_translType:"Relational",_processMetadata:function(){this.base();var a=this.metadata,b=this.J,c=this.options.categoriesCount;if(c!=null&&(!isFinite(c)||c<0))c=0;var d,e,g;if(this.options.isMultiValued)g=(e=i.parseDistinctIndexArray(this.options.measuresIndexes, -0,b-1))?e.length:0;var h;if(g==null)if(b>0&&b<=3&&(c==null||c===1)&&d==null){g=1;e=[b-1];c=b>=2?1:0;d=b>=3?1:0;h=c+d}else if(c!=null&&c>=b){c=h=b;g=d=0}else{g=c!=null?b-c:Infinity;e=f.query(a).where(function(n,o){return this._columnTypes[o]!==0},this).select(function(n){return n.colIndex}).take(g).array();g=e.length}if(h==null){h=b-g;if(h===0)d=c=0;else if(c!=null)if(c>h){c=h;d=0}else d=h-c;else{d=h>1?1:0;c=h-d}}a=this.options.seriesInRows;var j=[];if(h){d&&!a&&j.push({name:"S",count:d});c&&j.push({name:"C", -count:c});d&&a&&j.push({name:"S",count:d})}g&&j.push({name:"M",count:g});var l=f.range(0,b).array();e&&e.forEach(function(n){l.splice(n,1)});var m={};j.forEach(function(n){var o=n.count,p=n.name;m[p]=n;n.indexes=e&&p==="M"?e:l.splice(0,o)});this.M=g;this.S=d;this.C=c;var k=[];["S","C","M"].forEach(function(n){(n=m[n])&&f.array.append(k,n.indexes)});this._itemInfos=k.map(this._buildItemInfoFromMetadata,this);this._itemCrossGroupIndex={S:0,C:this.S,M:this.S+this.C};this._itemPerm=k},logVItem:function(){return this._logVItem(["S", -"C","M"],{S:this.S,C:this.C,M:this.M})},_configureTypeCore:function(){function a(j,l,m,k){for(l=b._itemCrossGroupIndex[l]+k;k>0;){var n=i.buildIndexedId(j,m);if(!b.complexTypeProj.isReadOrCalc(n)){c=b._nextAvailableItemIndex(c);if(c>=l)return;d.push({names:n,indexes:c});c++;k--}m++}}var b=this,c=0,d=[];this.S>0&&a("series","S",0,this.S);this.C>0&&a("category","C",0,this.C);this.M>0&&a("value","M",0,this.M);d&&d.forEach(this.defReader,this);var e=this.options.dataPartDimName;if(e&&!this.complexTypeProj.isReadOrCalc(e)){var g= -this.options.plot2DataSeriesIndexes;if(g!=null){var h=this._userDimsReadersByDim.series;h&&this._userRead(ab.call(this,g,h),e)}}},_executeCore:function(){var a=this._getDimensionsReaders(),b=this._itemPerm;return f.query(this._getItems()).select(function(c){c=u.permute(c,b);return this._readItem(c,a)},this)}});f.type("pvc.data.Atom").init(function(a,b,c,d,e){this.dimension=a;this.id=b==null?-f.nextId():f.nextId();this.value=b;this.label=c;if(d!==undefined)this.rawValue=d;this.key=e}).add({isVirtual:false, -rawValue:undefined,toString:function(){var a=this.label;if(a!=null)return a;a=this.value;return a!=null?""+a:""}});var Jb=1;f.type("pvc.data.Complex").init(function(a,b,c,d,e,g){this.id=Jb++;var h;if(a){h=a.owner;if(!d)d=a.atoms}this.owner=h||this;this.atoms=d?Object.create(d):{};var j=!!c;if(!c)c=h.type._dimsNames;var l=this.atoms;a=c.length;var m;if(b){var k=h._dimensions,n=function(q,s){var r=f.getOwn(k,q);if(s!=null){s=r.intern(s);if(!d||s!==d[q])l[q]=s}else r.intern(null)};if(j)for(j=0;j0},atoms:function(a){this._lazyInit&& -this._lazyInit();a=f.get(a,"visible");if(a==null)return this._atoms;a=!!a;this._visibleAtoms||(this._visibleAtoms={});return this._visibleAtoms[a]||(this._visibleAtoms[a]=ob.call(this,a))},indexes:function(a){this._lazyInit&&this._lazyInit();a=f.get(a,"visible");if(a==null)return u.range(0,this._atoms.length);a=!!a;this._visibleIndexes||(this._visibleIndexes={});return this._visibleIndexes[a]||(this._visibleIndexes[a]=nb.call(this,a))},atom:function(a){if(a==null||a==="")return this._nullAtom;if(a instanceof -i.data.Atom)return a;this._lazyInit&&this._lazyInit();return this._atomsByKey[this.type._key?this.type._key.call(null,a):a]||null},extent:function(a){var b=this.atoms(a),c=b.length;if(c){var d=this._nullAtom&&b[0].value==null?1:0,e=c-d;if(e>0){d=b[d];c=b[c-1];if(d!==c&&f.get(a,"abs",false)){a=c.value<0?-1:1;if((d.value<0?-1:1)===a){if(a<0){b=c;c=d;d=b}}else if(e>2){if(c.value<-d.value)c=d;d=f.array.binarySearch(b,0,this.type.comparer(),function(g){return g.value});if(d<0){d=~d;e=b[d-1];b=b[d];d=-e.value< -b.value?e:b}else d=b[d]}else if(c.value<-d.value){b=c;c=d;d=b}}return{min:d,max:c}}}},min:function(a){a=this.atoms(a);var b=a.length;if(b){var c=this._nullAtom&&a[0].value==null?1:0;return b>c?a[c]:undefined}},max:function(a){a=this.atoms(a);var b=a.length;return b&&a[b-1].value!=null?a[b-1]:undefined},sum:function(a){var b=!!f.get(a,"abs",false),c=f.get(a,"zeroIfNone",true),d=Da(a)+":"+b,e=f.getOwn(this._sumCache,d);if(e===undefined){var g=this.name;e=this.data.datums(null,a).reduce(function(h,j){j= -j.atoms[g].value;if(b&&j<0)j=-j;return h!=null?h+j:j},null);(this._sumCache||(this._sumCache={}))[d]=e}return c?e||0:e},percent:function(a,b){a=a instanceof i.data.Atom?a.value:a;if(!a)return 0;return(b=this.sum(f.create(b,{abs:true})))?Math.abs(a)/b:0},percentOverParent:function(a){var b=this.sum(a);if(!b)return 0;var c=this.data.parent;if(!c)return 1;return(a=c.dimensionsSumAbs(this.name,a))?Math.abs(b)/a:0},format:function(a,b){return""+(this.type._formatter?this.type._formatter.call(null,a,b): -"")},intern:function(a,b){if(a==null||a==="")return this._nullAtom||ga.call(this,a);if(a instanceof i.data.Atom){if(a.dimension!==this)throw f.error.operationInvalid("Atom is of a different dimension.");return a}var c,d,e=this.type;if(typeof a==="object"&&"v"in a){d=a.f;a=a.v;if(a==null||a==="")return this._nullAtom||ga.call(this)}if(b)c=a;else if(c=e._converter){c=c(a);if(c==null||c==="")return this._nullAtom||ga.call(this,a)}else c=a;var g=e.cast;if(g){c=g(c);if(c==null||c==="")return this._nullAtom|| -ga.call(this)}g=e._key;(g=""+(g?g(c):c))||f.fail.operationInvalid("Only a null value can have an empty key.");var h=this._atomsByKey[g];if(h){!b&&h.isVirtual&&delete h.isVirtual;return h}return Ba.call(this,e,a,g,c,d,b)},read:function(a,b){if(a==null||a==="")return null;var c,d=this.type;if(typeof a==="object"&&"v"in a){b=a.f;a=a.v;if(a==null||a==="")return null}c=(c=d._converter)?c(a):a;if(c==null||c==="")return null;var e=d.cast;if(e){c=e(c);if(c==null||c==="")return null}e=d._key;e=""+(e?e(c): -c);var g=this._atomsByKey[e];if(g)return{rawValue:a,key:e,value:g.value,label:""+(b==null?g.label:b)};if(b==null)b=(b=d._formatter)?b(c,a):c;b=""+b;return{rawValue:a,key:e,value:c,label:b}},dispose:function(){if(!this._disposed){ia(this._children,"parent");ia(this._linkChildren,"linkParent");this.parent&&ib.call(this.parent,this);this.linkParent&&kb.call(this.linkParent,this);fa.call(this);this._atoms=this._nullAtom=this._virtualNullAtom=this._lazyInit=null;this._disposed=true}}});f.type("pvc.data.Data", -i.data.Complex).init(function(a){a||f.fail.argumentRequired("keyArgs");this._visibleNotNullDatums=new f.Map;var b,c,d,e,g,h,j=this.parent=a.parent||null;if(j){this.root=j.root;this.depth=j.depth+1;this.type=j.type;g=a.datums||f.fail.argumentRequired("datums");b=j.owner;c=a.atoms||f.fail.argumentRequired("atoms");e=a.dimNames||f.fail.argumentRequired("dimNames");d=j.atoms}else{this.root=this;e=[];var l=a.linkParent||null;if(l){b=l.owner;this.type=b.type;g=a.datums||f.fail.argumentRequired("datums"); -this._leafs=[];d=l.atoms;h=f.get(a,"index",null);qb.call(l,this,h)}else{b=this;d={};if(a.labelSep)this.labelSep=a.labelSep;if(a.keySep)this.keySep=a.keySep;this.type=a.type||f.fail.argumentRequired("type");this._selectedNotNullDatums=new f.Map}}g&&na.call(this,g);this.owner=b;this._atomsBase=d;this._dimensions={};this.type.dimensionsList().forEach(this._initDimension,this);this.base(b,c,e,d,true);u.Dom.Node.call(this,null);delete this.nodeValue;this._children=this.childNodes;if(j){h=f.get(a,"index", -null);pb.call(j,this,h);this.absLabel=j.absLabel?f.string.join(b.labelSep,j.absLabel,this.label):this.label;this.absKey=j.absKey?f.string.join(b.keySep,j.absKey,this.key):this.key}else{this.absLabel=this.label;this.absKey=this.key}}).add(u.Dom.Node).add({parent:null,linkParent:null,_dimensions:null,_freeDimensionNames:null,_children:null,_linkChildren:null,_leafs:null,_childrenByKey:null,_visibleNotNullDatums:null,_selectedNotNullDatums:null,_groupByCache:null,_sumAbsCache:null,treeHeight:null,_groupOper:null, -_groupSpec:null,_groupLevel:null,_datums:null,_datumsById:null,depth:0,label:"",absLabel:"",_disposed:false,_isFlattenGroup:false,_isDegenerateFlattenGroup:false,_initDimension:function(a){this._dimensions[a.name]=new i.data.Dimension(this,a)},dimensions:function(a,b){if(a==null)return this._dimensions;var c=f.getOwn(this._dimensions,a);if(!c&&f.get(b,"assertExists",true))throw f.error.argumentInvalid("name","Undefined dimension '{0}'.",[a]);return c},freeDimensionNames:function(){if(!this._freeDimensionNames){var a= -this._freeDimensionNames=[];f.eachOwn(this._dimensions,function(b,c){b=this.atoms[c];if(!(b instanceof i.data.Atom)||b.value==null)a.push(c)},this)}return this._freeDimensionNames},isOwner:function(){return this.owner===this},children:function(){return this._children?f.query(this._children):f.query()},child:function(a){return this._childrenByKey?this._childrenByKey[a]||null:null},childCount:function(){return this._children?this._children.length:0},leafs:function(){return f.query(this._leafs)},count:function(){return this._datums.length}, -firstDatum:function(){return this._datums.length?this._datums[0]:null},singleDatum:function(){var a=this._datums;return a.length===1?a[0]:null},dispose:function(){if(!this._disposed){la.call(this);this._selectedNotNullDatums&&this._selectedNotNullDatums.clear();this._visibleNotNullDatums.clear();f.eachOwn(this._dimensions,function(a){a.dispose()});if(this.parent){this.parent.removeChild(this);this.parent=null}this.linkParent&&rb.call(this.linkParent,this);this._disposed=true}},disposeChildren:function(){la.call(this)}}); -i.data.Data.add({selectedCount:function(){if(!this.isOwner())return this.datums(null,{selected:true}).count();return this._selectedNotNullDatums.count},selectedDatums:function(){if(!this.isOwner())return this.datums(null,{selected:true}).array();return this._selectedNotNullDatums.values()},selectedDatumMap:function(){if(!this.isOwner()){var a=this.datums(null,{selected:true}).object({name:f.propGet("id")});return new f.Set(a)}return this._selectedNotNullDatums.clone()},visibleCount:function(){return this._visibleNotNullDatums.count}, -replaceSelected:function(a){f.array.is(a)||(a=a.array());var b=f.query(a).where(ta).object({name:Kb}),c=this.owner.clearSelected(function(d){return!f.hasOwn(b,d.id)});c|=i.data.Data.setSelected(a,true);return c},clearSelected:function(a){if(this.owner!==this)return this.owner.clearSelected(a);if(!this._selectedNotNullDatums.count)return false;var b;if(a){b=false;this._selectedNotNullDatums.values().filter(a).forEach(function(c){b=true;Aa.call(c);this._selectedNotNullDatums.rem(c.id)},this)}else{b= -true;this._selectedNotNullDatums.values().forEach(function(c){Aa.call(c)});this._selectedNotNullDatums.clear()}return b}});i.data.Data.setSelected=function(a,b){var c=0;a&&f.query(a).each(function(d){c|=d.setSelected(b)});return!!c};i.data.Data.toggleSelected=function(a,b){f.array.isLike(a)||(a=f.query(a).array());var c=f.query(a);b=b?c.any(ta):c.all(db);return this.setSelected(a,!b)};i.data.Data.setVisible=function(a,b){var c=0;a&&f.query(a).each(function(d){c|=d.setVisible(b)});return!!c};i.data.Data.toggleVisible= -function(a){f.array.isLike(a)||(a=f.query(a).array());var b=f.query(a).all(f.propGet("isVisible"));return i.data.Data.setVisible(a,!b)};f.space("pvc.data").FlatteningMode=f.set(f.makeEnum(["DfsPre","DfsPost"]),"None",0);f.type("pvc.data.GroupingSpec").init(function(a,b,c){this.type=b||null;var d=[];this.hasCompositeLevels=false;var e=[];this.levels=f.query(a||undefined).where(function(g){return g.dimensions.length>0}).select(function(g){d.push(g.id);f.array.append(e,g.dimensionNames());if(!this.hasCompositeLevels&& -g.dimensions.length>1)this.hasCompositeLevels=true;g._setAccDimNames(e.slice(0));return g},this).array();this._dimNames=e;this.depth=this.levels.length;this.isSingleDimension=(this.isSingleLevel=this.depth===1)&&!this.hasCompositeLevels;this.firstDimension=this.depth>0?this.levels[0].dimensions[0]:null;this.rootLabel=f.get(c,"rootLabel")||"";this.flatteningMode=f.get(c,"flatteningMode")||i.data.FlatteningMode.None;this._cacheKey=this._calcCacheKey();this.id=this._cacheKey+"##"+d.join("||")}).add({_calcCacheKey:function(a){return[f.get(a, -"flatteningMode")||this.flatteningMode,f.get(a,"reverse")||"false",f.get(a,"isSingleLevel")||this.isSingleLevel,f.get(a,"rootLabel")||this.rootLabel].join("#")},bind:function(a){this.type=a||f.fail.argumentRequired("type");this.levels.forEach(function(b){b.bind(a)})},dimensions:function(){return f.query(this.levels).prop("dimensions").selectMany()},dimensionNames:function(){return this._dimNames},view:function(a){return a.view(this.dimensionNames())},isDiscrete:function(){var a;return!this.isSingleDimension|| -!!(a=this.firstDimension)&&a.type.isDiscrete},firstDimensionType:function(){var a=this.firstDimension;return a&&a.type},firstDimensionName:function(){var a=this.firstDimensionType();return a&&a.name},firstDimensionValueType:function(){var a=this.firstDimensionType();return a&&a.valueType},isNull:function(){return!this.levels.length},ensure:function(a){var b;if(a){var c=this._calcCacheKey(a);if(c!==this._cacheKey){var d=f.lazy(this,"_groupingCache");(b=f.getOwn(d,c))||(b=d[c]=this._ensure(a))}}return b|| -this},_ensure:function(a){var b=this;if(f.get(a,"isSingleLevel")&&!b.isSingleLevel)return b._singleLevelGrouping(a);if(f.get(a,"reverse"))return b._reverse(a);var c=f.get(a,"flatteningMode")||b.flatteningMode;a=f.get(a,"rootLabel")||b.rootLabel;if(c!==b.flatteningMode||a!==b.rootLabel)return new i.data.GroupingSpec(b.levels,b.type,{flatteningMode:c,rootLabel:a});return b},_singleLevelGrouping:function(a){var b=!!f.get(a,"reverse"),c=this.dimensions().select(function(d){return b?new i.data.GroupingDimensionSpec(d.name, -!d.reverse,d.type.complexType):d});c=new i.data.GroupingLevelSpec(c,this.type);return new i.data.GroupingSpec([c],this.type,{flatteningMode:null,rootLabel:f.get(a,"rootLabel")||this.rootLabel})},_reverse:function(a){var b=f.query(this.levels).select(function(c){c=f.query(c.dimensions).select(function(d){return new i.data.GroupingDimensionSpec(d.name,!d.reverse,d.type.complexType)});return new i.data.GroupingLevelSpec(c,this.type)});return new i.data.GroupingSpec(b,this.type,{flatteningMode:f.get(a, -"flatteningMode")||this.flatteningMode,rootLabel:f.get(a,"rootLabel")||this.rootLabel})},toString:function(){return f.query(this.levels).select(function(a){return""+a}).array().join(", ")}});f.type("pvc.data.GroupingLevelSpec").init(function(a,b){var c=[],d=[];this.dimensions=f.query(a).select(function(g){c.push(g.id);d.push(g.name);return g}).array();this._dimNames=d;this.dimensionsInDefOrder=this.dimensions.slice(0);b&&this._sortDimensions(b);this.id=c.join(",");this.depth=this.dimensions.length; -var e=this;this.comparer=function(g,h){return e.compare(g,h)}}).add({_sortDimensions:function(a){a.sortDimensionNames(this.dimensionsInDefOrder,function(b){return b.name})},_setAccDimNames:function(a){this._accDimNames=a},accDimensionNames:function(){return this._accDimNames},dimensionNames:function(){return this._dimNames},bind:function(a){this._sortDimensions(a);this.dimensions.forEach(function(b){b.bind(a)})},compare:function(a,b){for(var c=0,d=this.depth;c0&&this._groupSpecRecursive(b,a,0);return b},_groupSpecRecursive:function(a,b,c){function d(n,o,p){var q=g[p];if(!j){n.children=[];n.groupSpec=e;n.groupLevelSpec=q}o=this._groupDatums(q,n,o,j);var s=p===h-1;var r=(q=j&&!m)?[]:n.datums;o.forEach(function(t){var A=t.datums;if(!(m&&s))t.datums=[];var x;if(j){f.array.lazy(n,"_children").push(t); -if(f.hasOwn(a.childrenByKey,t.key)){f.array.append(r,A);return}x=a.children.length;if(!k){a.children.push(t);a.childrenByKey[t.key]=t;n.isFlattenGroup=true}}else n.children.push(t);if(s)m||this._groupSpecRecursive(t,A,l);else d.call(this,t,A,p+1);f.array.append(r,t.datums);if(j&&k){if(f.hasOwn(a.childrenByKey,t.key)){t.isFlattenGroup||f.assert("Must be a parent for duplicate keys to exist.");if(t._children.length===1){a.children.splice(x,a.children.length-x);t.isDegenerateFlattenGroup=true}}a.children.push(t); -a.childrenByKey[t.key]=t;n.isFlattenGroup=true}},this);q&&this._groupSpecRecursive(n,r,l)}var e=this._groupSpecs[c],g=e.levels,h=g.length,j=!!e.flatteningMode,l=c+1,m=l>=this._groupSpecs.length,k=j&&e.flatteningMode===i.data.FlatteningMode.DfsPost;if(j){a.children=[];a.childrenByKey={};c={key:"",absKey:"",atoms:{},datums:[],label:e.rootLabel,dimNames:[]};if(!k){a.children.push(c);a.childrenByKey[""]=c}}else{if(a.isRoot)a.label=e.rootLabel;c=a}d.call(this,c,b,0);if(j){k&&a.children.push(c);a.datums= -c.datums}},_groupDatums:function(a,b,c,d){var e=[],g=new f.OrderedMap;f.query(c).each(function(h){var j=a.key(h),l=j.key,m=g.get(l);if(m)m.datums.push(h);else{m=j;m.datums=[h];if(d){f.copy(m.atoms,b.atoms);if(b.dimNames.length){j=h.owner.keySep;for(var k=j.length,n=m.absKey=b.absKey+j+l;n.lastIndexOf(j)===n.length-k;)n=n.substr(0,n.length-k);m.key=n}else m.absKey=l;m.dimNames=a.accDimensionNames()}h=f.array.insert(e,h,a.comparer);g.add(l,m,~h)}});return g},_generateData:function(a,b,c,d){var e,g; -if(a.isRoot)if(d){e=d;Fa.call(e,a.datums)}else{g=true;e=new i.data.Data({linkParent:c,datums:a.datums});e.treeHeight=a.treeHeight;e._groupOper=this}else{if(d)(e=f.get(c._childrenByKey,a.key))&&pa.call(e,a.datums);if(!e){g=true;var h,j;if(d&&(j=c._children))h=~f.array.binarySearch(j,a.datums[0],b.groupLevelSpec.comparer);e=new i.data.Data({parent:c,atoms:a.atoms,dimNames:a.dimNames,datums:a.datums,index:h})}}if(g){if(a.isFlattenGroup){e._isFlattenGroup=true;e._isDegenerateFlattenGroup=!!a.isDegenerateFlattenGroup}if(b= -a.label){e.label+=b;e.absLabel+=b}}if((b=a.children)&&b.length){if(g){e._groupSpec=a.groupSpec;e._groupLevelSpec=a.groupLevelSpec}b.forEach(function(l){this._generateData(l,a,e,d)},this)}else if(g&&!a.isRoot){g=e.root._leafs;e.leafIndex=g.length;g.push(e)}return e}});f.type("pvc.data.LinearInterpolationOper").init(function(a,b,c,d,e,g){this._newDatums=[];this._data=b;a=c.flatten(a,{ignoreNulls:false})._children;var h=this._serDatas1=d.isBound()?d.flatten(b).children().array():[null];this._isCatDiscrete= -c.grouping.isDiscrete();this._firstCatDim=!this._isCatDiscrete?b.owner.dimensions(c.firstDimensionName()):null;this._stretchEnds=g;var j=this._valDim=b.owner.dimensions(e.firstDimensionName()),l={visible:true,zeroIfNone:false};this._catInfos=a.map(function(m,k){var n=b._childrenByKey[m.key],o={data:n||m,value:m.value,isInterpolated:false,serInfos:null,index:k};o.serInfos=h.map(function(p){var q=n;if(q&&p)q=q._childrenByKey[p.key];var s=q?q.dimensions(j.name).sum(l):null;return{data:p,group:q,value:s, -isNull:s==null,catInfo:o}},this);return o});this._serCount=h.length;this._serStates=f.range(0,this._serCount).select(function(m){return new i.data.LinearInterpolationOperSeriesState(this,m)},this).array()}).add({interpolate:function(){for(var a;a=this._catInfos.shift();)a.serInfos.forEach(this._visitSeries,this);a=this._newDatums;a.length&&this._data.owner.add(a)},_visitSeries:function(a,b){this._serStates[b].visit(a)},nextUnprocessedNonNullCategOfSeries:function(a){for(var b=0,c=this._catInfos.length;b< -c;){var d=this._catInfos[b++].serInfos[a];if(!d.isNull)return d}}});f.type("pvc.data.LinearInterpolationOperSeriesState").init(function(a,b){this.interpolation=a;this.index=b;this._lastNonNull(null)}).add({visit:function(a){a.isNull?this._interpolate(a):this._lastNonNull(a)},_lastNonNull:function(a){if(arguments.length){this.__lastNonNull=a;this.__nextNonNull=undefined}return this.__lastNonNull},_nextNonNull:function(){return this.__nextNonNull},_initInterpData:function(){if(this.__nextNonNull=== -undefined){var a=this.__lastNonNull,b=this.__nextNonNull=this.interpolation.nextUnprocessedNonNullCategOfSeries(this.index)||null;if(b&&a){var c=b.value-a.value;if(this.interpolation._isCatDiscrete){b=b.catInfo.index-a.catInfo.index;b>=2||f.assert("Must have at least one interpolation point.");this._stepValue=c/b;this._middleIndex=~~(b/2);this._isOdd=(b-1)%2>0}else{a=+a.catInfo.value;b=+b.catInfo.value;this._steep=c/(b-a);this._middleCat=(b+a)/2}}}},_interpolate:function(a){this._initInterpData(); -var b=this.__nextNonNull,c=this.__lastNonNull,d=b||c;if(d){var e=this.interpolation,g=a.catInfo;if(b&&c)if(e._isCatDiscrete){d=g.index-c.catInfo.index;a=c.value+this._stepValue*d;b=this._isOdd?d=2||f.assert("Must have at least one interpolation point."); -this._middleIndex=~~(a/2);this._isOdd=(a-1)%2>0}else this._middleCat=(+b.catInfo.value+ +a.catInfo.value)/2}},_interpolate:function(a){this._initInterpData();var b=this.__nextNonNull,c=this.__lastNonNull,d=b||c;if(d){var e=this.interpolation;a=a.catInfo;if(b&&c)if(e._isCatDiscrete){d=a.index-c.catInfo.index;b=this._isOdd?d=7&&i.log("[GroupBy] Cache key hit '"+b+"'");else{if(i.debug>=7)i.log("[GroupBy] "+(b?"Cache key not found: '"+b+"'":"No Cache key"));d=a.execute();if(b)(c||(this._groupByCache={}))[b]=d}return d},where:function(a,b){a=this.datums(a,b);return new i.data.Data({linkParent:this,datums:a})},datums:function(a, -b){if(!a){if(!b)return f.query(this._datums);return qa(f.query(this._datums),b)}a=Ga.call(this,a,b);return Ha.call(this,a,b)},datum:function(a,b){a||f.fail.argumentRequired("whereSpec");a=Ga.call(this,a,b);return Ha.call(this,a,b).first()||null},dimensionsSumAbs:function(a,b){var c=a+":"+Da(b),d=f.getOwn(this._sumAbsCache,c);if(d==null){d=this.children().where(function(e){return!e._isFlattenGroup||e._isDegenerateFlattenGroup}).select(function(e){return Math.abs(e.dimensions(a).sum(b))},this).reduce(f.add, -0);(this._sumAbsCache||(this._sumAbsCache={}))[c]=d}return d}});i.data.Data.add({getInfo:function(){var a=["DATA SUMMARY",i.logSeparator," Dimension",i.logSeparator];f.eachOwn(this.dimensions(),function(b,c){var d=b.count(),e=b.type,g=[];g.push('"'+e.label+'"');g.push(e.valueTypeName);e.isComparable&&g.push("comparable");e.isDiscrete||g.push("continuous");e.isHidden&&g.push("hidden");a.push(" "+c+" ("+g.join(", ")+") ("+d+")\n\t"+b.atoms().slice(0,10).map(function(h){return h.label}).join(", ")+ -(d>10?"...":""))});return a.join("\n")},getValues:function(){return u.range(0,this.getCategoriesSize()).map(function(a){return this._getValuesForCategoryIndex(a)},this)},_getDimensionValues:function(a){return this.dimensions(a).atoms().map(function(b){return b.value})},_getDimensionVisibleValues:function(a){return this.dimensions(a).atoms({visible:true}).map(function(b){return b.value})},getSeries:function(){return this._getDimensionValues("series")},getVisibleSeriesIndexes:function(){return this.dimensions("series").indexes({visible:true})}, -getVisibleCategoriesIndexes:function(){return this.dimensions("category").indexes({visible:true})},getVisibleSeries:function(){return this._getDimensionVisibleValues("series")},getCategories:function(){return this._getDimensionValues("category")},getVisibleCategories:function(){return this._getDimensionVisibleValues("category")},_getValuesForCategoryIndex:function(a){var b=this.datums({category:this.dimensions("category").atoms()[a]}).uniqueIndex(function(c){return c.atoms.series.key});return this.dimensions("series").atoms().map(function(c){return(c= -f.getOwn(b,c.key))?c.atoms.value.value:null})},getSeriesSize:function(){var a=this.dimensions("series",{assertExists:false});return a?a.count():0},getCategoriesSize:function(){var a=this.dimensions("category",{assertExists:false});return a?a.count():0}});f.scope(function(){var a=f.makeEnum(["Interactive","ShowsActivity","ShowsSelection","ShowsTooltip","Selectable","Unselectable","Hoverable","Clickable","DoubleClickable","SelectableByClick","SelectableByRubberband","SelectableByFocusWindow","Animatable"]); -a.ShowsInteraction=a.ShowsActivity|a.ShowsSelection;a.Actionable=a.Hoverable|a.Clickable|a.DoubleClickable|a.SelectableByClick;a.HandlesEvents=a.Actionable|a.ShowsTooltip;a.HandlesClickEvent=a.Clickable|a.SelectableByClick;f.type("pvc.visual.Interactive").addStatic(a).addStatic({ShowsAny:a.ShowsInteraction|a.ShowsTooltip,SelectableAny:a.Selectable|a.SelectableByClick|a.SelectableByRubberband|a.SelectableByFocusWindow}).add({_ibits:-1}).add(f.query(f.ownKeys(a)).object({name:f.firstLowerCase,value:function(b){var c= -a[b];return function(){return!!(this._ibits&c)}}}))});f.type("pvc.visual.Scene").init(function(a,b){if(i.debug>=4)this.id=f.nextId("scene");this._renderId=0;this.renderState={};u.Dom.Node.call(this,null);this.parent=a||null;if(a){this.root=a.root;var c=f.get(b,"index",null);a.insertAt(this,c)}else{this.root=this;this._active=null;this._panel=f.get(b,"panel")||f.fail.argumentRequired("panel","Argument is required on root scene.")}var d,e,g,h,j,l;if((b=f.array.to(f.get(b,"source")))&&b.length){this.source= -b;d=b[0];if(d instanceof i.data.Data){e=d;j=b;g=e.firstDatum()||f.query(j).select(function(m){return m.firstDatum()}).first(f.notNully)}else{d instanceof i.data.Datum||f.assert("not a datum");g=d;h=b}b=d.atoms;l=g&&g.atoms||d.atoms}else b=a?(l=Object.create(a.atoms)):(l={});this.atoms=b;this.firstAtoms=l;j&&(this.groups=j);e&&(this.group=e);h&&(this._datums=h);g&&(this.datum=g);if(!d||d.isNull)this.isNull=true;this.vars=a?Object.create(a.vars):{}}).add(u.Dom.Node).add(i.visual.Interactive).add({source:null, -groups:null,group:null,_datums:null,datum:null,isNull:false,data:function(){var a=this.group;if(!a){for(var b=this;!a&&(b=b.parent);)a=b.group;if(!a)a=this.panel.data}return a},datums:function(){return this.groups?f.query(this.groups).selectMany(function(a){return a.datums()}):this._datums?f.query(this._datums):f.query()},format:function(a){return f.format(a,this._formatScope,this)},_formatScope:function(a){if(a.charAt(0)==="#"){a=a.substr(1).split(".");if(a.length>2)throw f.error.operationInvalid("Scene format mask is invalid."); -var b=this.firstAtoms[a[0]];if(b){if(a.length>1)switch(a[1]){case "value":return b.value;case "label":break;default:throw f.error.operationInvalid("Scene format mask is invalid.");}return b}return null}return f.getPath(this.vars,a)},isRoot:function(){return this.root===this},panel:function(){return this.root._panel},chart:function(){return this.root._panel.chart},compatVersion:function(){return this.root._panel.compatVersion()},children:function(){return this.childNodes?f.query(this.childNodes):f.query()}, -leafs:function(){function a(c){for(;c.childNodes.length;)c=c.childNodes[0];return c}var b=this;return f.query(function(c){if(!c){c=a(b);if(c===b)return 0;this.item=c;return 1}if(c=this.item.nextSibling){this.item=c;return 1}for(var d=this.item;d!==b&&(d=d.parentNode);)if(c=d.nextSibling){this.item=a(c);return 1}return 0})},anyInteraction:function(){return!!this.root._active||this.anySelected()},isActive:false,setActive:function(a){a=!!a;if(this.isActive!==a)Ia.call(this.root,this.isActive?null:this)}, -clearActive:function(){return Ia.call(this.root,null)},anyActive:function(){return!!this.root._active},active:function(){return this.root._active},activeSeries:function(){var a=this.active(),b;return a&&(b=a.vars.series)&&b.value},isActiveSeries:function(){if(this.isActive)return true;var a=this.renderState.isActiveSeries;if(a==null){var b;a=(b=this.activeSeries())!=null&&b===this.vars.series.value;this.renderState.isActiveSeries=a}return a},isActiveDatum:function(){if(this.isActive)return true;var a= -this.renderState.isActiveDatum;if(a==null){a=(a=this.active())?this.group&&a.group===this.group||this.datum&&a.datum===this.datum:false;this.renderState.isActiveDatum=a}return a},isActiveDescendantOrSelf:function(){if(this.isActive)return true;return f.lazy(this.renderState,"isActiveDescOrSelf",this._calcIsActiveDescOrSelf,this)},_calcIsActiveDescOrSelf:function(){var a=this.active();if(a)for(;a=a.parent;)if(a===this)return true;return false},isVisible:function(){return this._visibleData().is},anyVisible:function(){return this._visibleData().any}, -_visibleData:function(){return f.lazy(this.renderState,"_visibleData",this._createVisibleData,this)},_createVisibleData:function(){var a=this.chart().data.owner.visibleCount()>0,b=a&&this.datums().any(f.propGet("isVisible"));return{any:a,is:b}},isSelected:function(){return this._selectedData().is},anySelected:function(){return this._selectedData().any},_selectedData:function(){return f.lazy(this.renderState,"_selectedData",this._createSelectedData,this)},_createSelectedData:function(){var a=this.chart().data.owner.selectedCount()> -0,b=a&&this.datums().any(ta);return{any:a,is:b}},select:function(a){var b=this,c=b.datums().array();if(c.length){var d=b.chart();d._updatingSelections(function(){if((c=d._onUserSelection(c))&&c.length)d.options.ctrlSelectMode&&f.get(a,"replace",true)?d.data.replaceSelected(c):i.data.Data.toggleSelected(c)})}},isSelectedDescendantOrSelf:function(){if(this.isSelected())return true;return f.lazy(this.renderState,"isSelectedDescOrSelf",this._calcIsSelectedDescOrSelf,this)},_calcIsSelectedDescOrSelf:function(){var a= -this.firstChild;if(a){do if(a.isSelectedDescendantOrSelf())return true;while(a=a.nextSibling)}return false},toggleVisible:function(){i.data.Data.toggleVisible(this.datums())&&this.chart().render(true,true,false)}});i.visual.Scene.prototype.variable=function(a,b){var c=this,d;if(a in c){if(b!==undefined)d=f.set({},"_"+a+"EvalCore",f.fun.to(b))}else{if(!c.hasOwnProperty("_vars"))c._vars=f.create(c._vars);c._vars[a]=true;d={};var e="_"+a+"Eval";d[a]=xb(a,e);a=e+"Core";f.hasOwn(c,e)||(d[e]=f.methodCaller(a)); -f.hasOwn(c,a)||(d[a]=f.fun.to(b===undefined?null:b))}d&&c.constructor.add(d);return c};var I=i.visual.ValueLabelVar=function(a,b,c,d){this.value=a;this.label=b;if(c!==undefined)this.rawValue=c;if(d!==undefined)this.absLabel=d};f.set(I.prototype,"rawValue",undefined,"absLabel",undefined,"setValue",function(a){this.value=a;return this},"setLabel",function(a){this.label=a;return this},"clone",function(){return new I(this.value,this.label,this.rawValue)},"toString",function(){var a=this.label||this.value; -return a==null?"":typeof a!=="string"?""+a:a});I.fromComplex=function(a){return a?new I(a.value,a.label,a.rawValue,a.absLabel):new I(null,"",null)};I.fromAtom=I.fromComplex;f.type("pvc.visual.Context").init(function(a,b,c){this.chart=a.chart;this.panel=a;Ka.call(this,b,c)}).add({isPinned:false,pin:function(){this.isPinned=true;return this},compatVersion:function(){return this.panel.compatVersion()},finished:function(a){return this.sign.finished(a)},delegate:function(a){return this.sign.delegate(a)}, -getV1Series:function(){var a;return f.nullyTo(this.scene.firstAtoms&&(a=this.scene.firstAtoms[this.panel._getV1DimName("series")])&&a.rawValue,"Series")},getV1Category:function(){var a;return this.scene.firstAtoms&&(a=this.scene.firstAtoms[this.panel._getV1DimName("category")])&&a.rawValue},getV1Value:function(){var a;return this.scene.firstAtoms&&(a=this.scene.firstAtoms[this.panel._getV1DimName("value")])&&a.value},getV1Datum:function(){return this.panel._getV1Datum(this.scene)},select:function(a){return this.scene.select(a)}, -toggleVisible:function(){return this.scene.toggleVisible()},click:function(){var a=this;a.clickable()&&a.panel._onClick(a);if(a.selectableByClick()){var b=a.event;a.select({replace:!b||!b.ctrlKey})}},doubleClick:function(){this.doubleClickable()&&this.panel._onDoubleClick(this)},clickable:function(){var a=this;return(a.sign?a.sign.clickable():a.panel.clickable())&&(!a.scene||a.scene.clickable())},selectableByClick:function(){var a=this;return(a.sign?a.sign.selectableByClick():a.panel.selectableByClick())&& -(!a.scene||a.scene.selectableByClick())},doubleClickable:function(){var a=this;return(a.sign?a.sign.doubleClickable():a.panel.doubleClickable())&&(!a.scene||a.scene.doubleClickable())},hoverable:function(){var a=this;return(a.sign?a.sign.hoverable():a.panel.hoverable())&&(!a.scene||a.scene.hoverable())}});if(Object.defineProperty)try{Object.defineProperty(i.visual.Context.prototype,"parent",{get:function(){throw f.error.operationInvalid("The 'this.parent.index' idiom has no equivalent in this version. Please try 'this.pvMark.parent.index'."); -}})}catch(Sb){}f.space("pvc.visual").TraversalMode=f.makeEnum(["Tree","FlattenedSingleLevel","FlattenDfsPre","FlattenDfsPost"]);f.type("pvc.visual.Role").init(function(a,b){this.name=a;this.label=f.get(b,"label")||i.buildTitleFromName(a);this.index=f.get(b,"index")||0;this.dimensionDefaults=f.get(b,"dimensionDefaults")||{};if(f.get(b,"isRequired",false))this.isRequired=true;if(f.get(b,"autoCreateDimension",false))this.autoCreateDimension=true;if(a=f.get(b,"defaultSourceRole"))this.defaultSourceRoleName= -a;if(a=f.get(b,"defaultDimension"))this.defaultDimensionName=a;if(!a&&this.autoCreateDimension)throw f.error.argumentRequired("defaultDimension");var c;a=f.get(b,"requireIsDiscrete");if(a!=null)a||(c=true);if(c!=null)if(c=f.get(b,"requireSingleDimension",false)){if(f.get(b,"isMeasure",false)){this.isMeasure=true;if(f.get(b,"isPercent",false))this.isPercent=true}var d=f.get(b,"valueType",null);if(d!==this.valueType){this.valueType=d;this.dimensionDefaults.valueType=d}}if(c!==this.requireSingleDimension)this.requireSingleDimension= -c;if(a!=this.requireIsDiscrete){this.requireIsDiscrete=!!a;this.dimensionDefaults.isDiscrete=this.requireIsDiscrete}b=f.get(b,"traversalMode");if(b!=null&&b!==this.traversalMode)this.traversalMode=b}).add({isRequired:false,requireSingleDimension:false,valueType:null,requireIsDiscrete:null,isMeasure:false,isPercent:false,defaultSourceRoleName:null,defaultDimensionName:null,grouping:null,traversalMode:i.visual.TraversalMode.FlattenedSingleLevel,rootLabel:"",autoCreateDimension:false,isReversed:false, -label:null,sourceRole:null,isDefaultSourceRole:false,firstDimensionType:function(){var a=this.grouping;return a&&a.firstDimensionType()},firstDimensionName:function(){var a=this.grouping;return a&&a.firstDimensionName()},firstDimensionValueType:function(){var a=this.grouping;return a&&a.firstDimensionValueType()},isDiscrete:function(){var a=this.grouping;return a&&a.isDiscrete()},setSourceRole:function(a,b){this.sourceRole=a;this.isDefaultSourceRole=!!b},setIsReversed:function(a){if(a)this.isReversed= -true;else delete this.isReversed},setTraversalMode:function(a){var b=i.visual.TraversalMode;a=f.nullyTo(a,b.FlattenedSingleLevel);if(a!==this.traversalMode)if(a===b.FlattenedSingleLevel)delete this.traversalMode;else this.traversalMode=a},setRootLabel:function(a){if(a!==this.rootLabel){if(a)this.rootLabel=a;else delete this.rootLabel;this.grouping&&this._updateBind(this.grouping)}},flatten:function(a,b){var c=this.flattenedGrouping(b)||f.fail.operationInvalid("Role is unbound.");return a.groupBy(c, -b)},flattenedGrouping:function(a){var b=this.grouping;if(b){a||(a={});var c=a.flatteningMode;if(c==null)c=a.flatteningMode=this._flatteningMode();if(a.isSingleLevel==null&&!c)a.isSingleLevel=true;if(a.flatteningMode==null)a.flatteningMode=this._flatteningMode();return b.ensure(a)}},_flatteningMode:function(){var a=i.visual.TraversalMode,b=i.data.FlatteningMode;switch(this.traversalMode){case a.FlattenDfsPre:return b.DfsPre;case a.FlattenDfsPost:return b.DfsPost}return a.None},select:function(a,b){var c= -this.grouping;if(c){f.setUDefaults(b,"flatteningMode",i.data.FlatteningMode.None);return a.groupBy(c.ensure(b),b)}},view:function(a){var b=this.grouping;if(b)return b.view(a)},preBind:function(a){this.__grouping=a;return this},isPreBound:function(){return!!this.__grouping},preBoundGrouping:function(){return this.__grouping},isBound:function(){return!!this.grouping},postBind:function(a){var b=this.__grouping;if(b){delete this.__grouping;b.bind(a);this.bind(b)}return this},bind:function(a){a=this._validateBind(a); -this._updateBind(a);return this},_validateBind:function(a){if(a)if(a.isNull())a=null;else{if(this.requireSingleDimension&&!a.isSingleDimension)throw f.error.operationInvalid("Role '{0}' only accepts a single dimension.",[this.name]);var b=this.valueType,c=this.requireIsDiscrete;a.dimensions().each(function(d){d=d.type;if(b&&d.valueType!==b)throw f.error.operationInvalid("Role '{0}' cannot be bound to dimension '{1}'. \nIt only accepts dimensions of type '{2}' and not of type '{3}'.",[this.name,d.name, -i.data.DimensionType.valueTypeName(b),d.valueTypeName]);if(c!=null&&d.isDiscrete!==c)if(c)d._toDiscrete();else throw f.error.operationInvalid("Role '{0}' cannot be bound to dimension '{1}'. \nIt only accepts {2} dimensions.",[this.name,d.name,c?"discrete":"continuous"]);},this)}return a},_updateBind:function(a){this.grouping&&this.grouping.dimensions().each(function(b){b.type&&$a.call(b.type,this)},this);if(this.grouping=a){this.grouping=this.grouping.ensure({reverse:this.isReversed,rootLabel:this.rootLabel}); -this.grouping.dimensions().each(function(b){Za.call(b.type,this)},this)}}});f.type("pvc.visual.RoleVarHelper").init(function(a,b,c){var d=f.get(c,"hasPercentSubVar",false),e=f.get(c,"roleVar"),g=this.grouping=b&&b.grouping;if(g){this.role=b;this.sourceRoleName=b.sourceRole&&b.sourceRole.name;var h=a.panel();this.panel=h;if(!g.isDiscrete()){this.rootContDim=h.data.owner.dimensions(g.firstDimensionName());if(d)this.percentFormatter=h.chart.options.percentValueFormat}}if(!e){if(!b)throw f.error.operationInvalid("Role is not defined, so the roleVar argument is required."); -e=b.name}if(!g){b=a.vars[e]=new I(null,"");if(d)b.percent=new I(null,"")}this.roleVarName=e;a["is"+f.firstUpperCase(e)+"Bound"]=!!g;if(f.get(c,"allowNestedVars"))this.allowNestedVars=true}).add({allowNestedVars:false,isBound:function(){return!!this.grouping},onNewScene:function(a,b){if(this.grouping){var c=this.roleVarName;if(!(this.allowNestedVars?f.hasOwnProp.call(a.vars,c):a.vars[c])){var d=this.sourceRoleName;if(d)if(d=f.getOwn(a.vars,d)){a.vars[c]=d.clone();return}if(b){var e;if(b=this.rootContDim){var g; -var h=(d=a.group)?d.singleDatum():a.datum;if(h){if(!h.isNull){e=I.fromAtom(h.atoms[b.name]);if(e.value!=null&&this.percentFormatter)if(d){d=d.dimensions(b.name);g=d.percentOverParent({visible:true})}else g=a.data().dimensions(b.name).percent(e.value)}}else if(d){d=d.dimensions(b.name);h=d.sum({visible:true,zeroIfNone:false});if(h!=null){e=b.format(h);e=new I(h,e,h);if(this.percentFormatter)g=d.percentOverParent({visible:true})}}if(e&&this.percentFormatter)e.percent=e.value==null?new I(null,""):new I(g, -this.percentFormatter.call(null,g))}else if((g=a.datum)&&!g.isNull){e=this.grouping.view(g);e=I.fromComplex(e)}if(!e){e=new I(null,"");if(this.percentFormatter)e.percent=new I(null,"")}a.vars[c]=e}}}}});O.prototype.getSign=function(){return this.sign||yb(this)};O.prototype.getScene=function(){return this.getSign().scene};O.prototype.getContext=function(){return this.getSign().context()};f.type("pvc.visual.BasicSign").init(function(a,b){this.chart=a.chart;this.panel=a;this.pvMark=b;!b.sign||f.assert("Mark already has an attached Sign."); -b.sign=this;b.__buildInstance=b.buildInstance;b.buildInstance=this._dispatchBuildInstance}).add({compatVersion:function(){return this.chart.compatVersion()},localProperty:function(a,b){this.pvMark.localProperty(a,b);return this},lock:function(a,b){return this.lockMark(a,this._bindWhenFun(b,a))},optional:function(a,b,c){return this.optionalMark(a,this._bindWhenFun(b,a),c)},lockMark:function(a,b){this.pvMark.lock(a,b);return this},optionalMark:function(a,b,c){this.pvMark[a](b,c);return this},delegate:function(a, -b){return this.pvMark.delegate(a,b)},delegateExtension:function(a){return this.pvMark.delegate(a,i.extensionTag)},hasDelegate:function(a){return this.pvMark.hasDelegate(a)},_createPropInterceptor:function(a,b){var c=this,d=a==="data";return function(){var e=this.sign;if(!e||e!==c)return c._getPvSceneProp(a,this.index);if(!d){var g=this.scene[this.index];if(!e.scene||e.scene!==g.data)c._inContext(g.data,g)}return b.apply(c,arguments)}},_getPvSceneProp:function(a,b){var c=this.pvMark,d=c.scene;if(d){b= -c.hasOwnProperty("index")?c.index:Math.min(b,d.length-1);if(b!=null)return d[b][a]}throw f.error.operationInvalid("Cannot evaluate inherited property.");},_bindWhenFun:function(a,b){if(f.fun.is(a)){var c=this;return c._createPropInterceptor(b,function(d){return a.call(c,d)})}return a},_lockDynamic:function(a,b){var c=this;return c.lockMark(a,c._createPropInterceptor(a,function(d){return c[b].call(c,d)}))},_dispatchBuildInstance:function(a){function b(){this.__buildInstance(a)}this.sign._inContext(a.data, -a,b,this)},_inContext:function(a,b,c,d){var e=this.pvMark;b||(b=e.scene[e.index]);a||(a=b.data||f.assert("A scene is required!"));var g=a.childIndex(),h,j,l,m=this.pvInstance;if(m){h=this.scene;j=this.index;l=this.state}this.pvInstance=b;this.scene=a;this.index=g<0?0:g;wb.call(a,e.renderId());this.state={};if(c)try{return c.call(d,b)}finally{this.state=l;this.pvInstance=m;this.scene=h;this.index=j}},context:function(a){var b;if(a||!(b=this.state))return this._createContext();return b.context||(b.context= -this._createContext())},_createContext:function(){return new i.visual.Context(this.panel,this.pvMark)}});f.type("pvc.visual.Sign",i.visual.BasicSign).init(function(a,b,c){var d=this;d.base(a,b,c);d._ibits=a._ibits;var e=f.get(c,"extensionId");if(e!=null)d.extensionAbsIds=f.array.to(a._makeExtensionAbsId(e));d.isActiveSeriesAware=f.get(c,"activeSeriesAware",true);if(d.isActiveSeriesAware){a=(a=a.visualRoles)&&a.series;if(!a||!a.isBound())d.isActiveSeriesAware=false}b.wrapper(f.get(c,"wrapper")||d.createDefaultWrapper()); -f.get(c,"freeColor",true)||d._bindProperty("fillStyle","fillColor","color")._bindProperty("strokeStyle","strokeColor","color")}).postInit(function(a,b,c){this._addInteractive(c);a._addSign(this)}).add({createDefaultWrapper:function(){var a=this;return function(b){return function(c){return b.call(a.context(),c)}}},property:function(a){var b=f.firstUpperCase(a),c="base"+b,d="default"+b,e="normal"+b,g="interactive"+b;b={};b[a]=function(h){this._finished=false;this._arg=h;var j=this[c](h);if(j==null)return null; -if(this._finished)return j;j=this.showsInteraction()&&this.anyInteraction()?this[g](j,h):this[e](j,h);this._arg=null;return j};b[c]=function(){return this.delegateExtension()};b[d]=function(){};b[e]=function(h){return h};b[g]=function(h){return h};this.constructor.add(b);return this},anyInteraction:function(){return this.scene.anyInteraction()},finished:function(a){this._finished=true;return a},applyExtensions:function(){if(!this._extended){this._extended=true;var a=this.extensionAbsIds;a&&a.forEach(function(b){this.panel.extendAbs(this.pvMark, -b)},this)}return this},intercept:function(a,b){b=this._createPropInterceptor(a,b);return this._intercept(a,b)},lockDimensions:function(){this.pvMark.lock("left").lock("right").lock("top").lock("bottom").lock("width").lock("height");return this},_extensionKeyArgs:{tag:i.extensionTag},_bindProperty:function(a,b,c){var d=this;c||(c=b);var e="default"+f.firstUpperCase(c);if(f.fun.is(d[e]))d.pvMark.hasDelegateValue(a,i.extensionTag)||d.pvMark.intercept(a,function(){return d[e](d._arg)},d._extensionKeyArgs); -c=this._createPropInterceptor(a,function(){return d[b]()});return d._intercept(a,c)},_intercept:function(a,b){var c=this.pvMark,d=this.extensionAbsIds;d&&f.query(d).select(function(e){return this.panel._getExtensionAbs(e,a)},this).where(f.notUndef).each(function(e){e=c.wrap(e,a);c.intercept(a,e,this._extensionKeyArgs)},this);(c._intercepted||(c._intercepted={}))[a]=true;c.intercept(a,b);return this}}).prototype.property("color").constructor.add(i.visual.Interactive).add({extensionAbsIds:null,_addInteractive:function(a){var b= -this,c=f.get;if(b.interactive()){var d=b._ibits,e=i.visual.Interactive;if(c(a,"noTooltip"))d&=~e.ShowsTooltip;if(c(a,"noHover"))d&=~e.Hoverable;if(c(a,"noClick"))d&=~e.Clickable;if(c(a,"noDoubleClick"))d&=~e.DoubleClickable;if(c(a,"noSelect"))d&=~e.SelectableAny;else if(this.selectable()){if(c(a,"noClickSelect"))d&=~e.SelectableByClick;if(c(a,"noRubberSelect"))d&=~e.SelectableByRubberband}if(b.showsInteraction()){if(c(a,"showsInteraction")===false)d&=~e.ShowsInteraction;if(b.showsActivity())if(c(a, -"showsActivity")===false)d&=~e.ShowsActivity;if(b.showsSelection())if(c(a,"showsSelection")===false)d&=~e.ShowsSelection}b._ibits=d}if(b.handlesEvents()){b.showsTooltip()&&b._addPropTooltip(c(a,"tooltipArgs"));b.hoverable()&&b._addPropHoverable();b.handlesClickEvent()&&b._addPropClick();b.doubleClickable()&&b._addPropDoubleClick()}else b.pvMark.events("none")},fillColor:function(){return this.color("fill")},strokeColor:function(){return this.color("stroke")},defaultColor:function(){return this.defaultColorSceneScale()(this.scene)}, -dimColor:function(a,b){if(b==="text")return i.toGrayScale(a,-0.75,null,null);return i.toGrayScale(a,-0.3,null,null)},defaultColorSceneScale:function(){return f.lazy(this,"_defaultColorSceneScale",this._initDefColorScale,this)},_initDefColorScale:function(){var a=this.panel.axes.color;return a?a.sceneScale({sceneVarName:"color"}):f.fun.constant(i.defaultColor)},mayShowActive:function(a){if(!this.showsActivity())return false;var b=this.scene;return b.isActive||!a&&this.isActiveSeriesAware&&b.isActiveSeries()|| -b.isActiveDatum()},mayShowNotAmongSelected:function(){return this.mayShowAnySelected()&&!this.scene.isSelected()},mayShowSelected:function(){return this.showsSelection()&&this.scene.isSelected()},mayShowAnySelected:function(){return this.showsSelection()&&this.scene.anySelected()},_addPropTooltip:function(a){if(!this.pvMark.hasTooltip){var b=f.create(this.chart._tooltipOptions,f.get(a,"options"));b.isLazy=f.get(a,"isLazy",true);var c=f.get(a,"buildTooltip")||this._getTooltipFormatter(b);if(c){b.isEnabled= -this._isTooltipEnabled.bind(this);(a=f.get(a,"tipsyEvent"))||(a="mouseover");this.pvMark.localProperty("tooltip").tooltip(this._createTooltipProp(c,b.isLazy)).title(f.fun.constant("")).ensureEvents().event(a,u.Behavior.tipsy(b)).hasTooltip=true}}},_getTooltipFormatter:function(a){return this.panel._getTooltipFormatter(a)},_isTooltipEnabled:function(){return this.panel._isTooltipEnabled()},_createTooltipProp:function(a,b){var c=this,d;d=b?function(){var e=c.context(true),g;return function(){if(e){g= -a(e);e=null}return g}}:function(){var e=c.context();return a(e)};return function(){var e=c.scene;if(e&&!e.isIntermediate&&e.showsTooltip())return d()}},_addPropHoverable:function(){var a=this.panel;this.pvMark.ensureEvents().event("mouseover",function(b){if(b.hoverable()&&!a.selectingByRubberband()&&!a.animating()){b.setActive(true);a.renderInteractive()}}).event("mouseout",function(b){b.hoverable()&&!a.selectingByRubberband()&&!a.animating()&&b.clearActive()&&a.renderInteractive()})},_ignoreClicks:0, -_propCursorClick:function(a){a=this._ibits&a._ibits;var b=i.visual.Interactive;return a&b.HandlesClickEvent||a&b.DoubleClickable?"pointer":null},_addPropClick:function(){var a=this;a.pvMark.cursor(a._propCursorClick.bind(a)).ensureEvents().event("click",a._handleClick.bind(a))},_addPropDoubleClick:function(){var a=this;a.pvMark.cursor(a._propCursorClick.bind(a)).ensureEvents().event("dblclick",a._handleDoubleClick.bind(a))},_handleClick:function(){var a=this,b=a.pvMark,c=b.instance().data;if(a.doubleClickable()&& -c.doubleClickable()){var d=b.scene,e=b.index,g=u.event;window.setTimeout(function(){if(a._ignoreClicks)a._ignoreClicks--;else try{u.event=g;b.context(d,e,function(){a._handleClickCore()})}catch(h){u.error(h)}finally{delete u.event}},a.chart.options.doubleClickMaxDelay||300)}else if(a._ignoreClicks)a._ignoreClicks--;else a._handleClickCore()},_handleClickCore:function(){var a=this,b=a.pvMark.instance();a._inContext(b.data,b,function(){a._onClick(a.context())},a)},_handleDoubleClick:function(){var a= -this,b=a.pvMark.instance();if(b.data.doubleClickable()){a._ignoreClicks=2;a._inContext(b.data,b,function(){a._onDoubleClick(a.context())},a)}},_onClick:function(a){a.click()},_onDoubleClick:function(a){a.doubleClick()}});f.type("pvc.visual.Panel",i.visual.Sign).init(function(a,b,c){var d=f.get(c,"panel");if(!d){d=f.get(c,"panelType")||u.Panel;d=b.add(d)}this.base(a,d,c)}).add({_addInteractive:function(a){a=f.setDefaults(a,"noSelect",true,"noHover",true,"noTooltip",true,"noClick",true,"noDoubleClick", -true);this.base(a)}});f.type("pvc.visual.Label",i.visual.Sign).init(function(a,b,c){b=b.add(u.Label);this.base(a,b,c)}).add({_addInteractive:function(a){a=f.setDefaults(a,"noSelect",true,"noHover",true,"noTooltip",true,"noClick",true,"noDoubleClick",true,"showsInteraction",false);this.base(a)},defaultColor:f.fun.constant(u.Color.names.black)});f.type("pvc.visual.ValueLabel",i.visual.Label).init(function(a,b,c){b=f.get(c,"noAnchor",false)?b:b.anchor(a.valuesAnchor);if(c&&c.extensionId==null)c.extensionId= -"label";this.base(a,b,c);this._bindProperty("text","text");this.pvMark.font(a.valuesFont);this._bindProperty("textStyle","textColor","color")}).prototype.property("text").property("textStyle").constructor.addStatic({maybeCreate:function(a,b,c){return a.valuesVisible&&a.valuesMask?new i.visual.ValueLabel(a,b,c):null},isNeeded:function(a){return a.valuesVisible&&a.valuesMask}}).add({_addInteractive:function(a){a=f.setDefaults(a,"showsInteraction",true,"noSelect",true,"noTooltip",true,"noClick",true, -"noDoubleClick",true,"noHover",true);this.base(a)},defaultText:function(){return this.scene.format(this.panel.valuesMask)},normalText:function(a){return this.trimText(a)},interactiveText:function(a){return this.showsActivity()&&this.scene.isActive?a:this.trimText(a)},trimText:function(a){return a},textColor:function(){return this.color("text")},backgroundColor:function(a){var b=this.state;if(!b)return this.calcBackgroundColor(a);b=f.lazy(b,"bgColorCache");var c=f.getOwn(b,a);c||(c=b[a]=this.calcBackgroundColor(a)); -return c},calcBackgroundColor:f.fun.constant(u.Color.names.white),optimizeLegibilityColor:function(a){if(this.panel.valuesOptimizeLegibility)return this.backgroundColor().isDark()?a.complementary().alpha(0.9):a;return a},normalColor:function(a,b){return this.optimizeLegibilityColor(a,b)},interactiveColor:function(a,b){if(!this.mayShowActive()&&this.mayShowNotAmongSelected())return this.dimColor(a,b);return this.optimizeLegibilityColor(a,b)}});f.type("pvc.visual.Dot",i.visual.Sign).init(function(a, -b,c){b=b.add(u.Dot);var d=f.get(c,"proto");d&&b.extend(d);c=f.setDefaults(c,"freeColor",false);this.base(a,b,c);if(!f.get(c,"freePosition",false)){c=a.isOrientationVertical()?"left":"bottom";a=a.anchorOrtho(c);this._lockDynamic(c,"x")._lockDynamic(a,"y")}this._bindProperty("shape","shape")._bindProperty("shapeRadius","radius")._bindProperty("shapeSize","size");this.optional("strokeDasharray",undefined).optional("lineWidth",1.5)}).prototype.property("size").property("shape").constructor.add({y:f.fun.constant(0), -x:f.fun.constant(0),radius:function(){this.state.radius=this.delegateExtension()},baseSize:function(){var a=this.state.radius;return a!=null?f.sqr(a):this.base()},defaultSize:function(){return 12},interactiveSize:function(a){return this.mayShowActive(true)?Math.max(a,5)*2.5:a},interactiveColor:function(a,b){if(this.mayShowActive(true)){if(b==="stroke")return a.brighter(1)}else if(this.mayShowNotAmongSelected()){if(this.mayShowActive())return a.alpha(0.8);switch(b){case "fill":return this.dimColor(a, -b);case "stroke":return a.alpha(0.45)}}return this.base(a,b)}});f.type("pvc.visual.DotSizeColor",i.visual.Dot).init(function(a,b,c){this.base(a,b,c);var d=this.compatVersion()<=1;this._bindProperty("lineWidth","strokeWidth").intercept("visible",function(){if(!this.canShow())return false;var g=this.delegateExtension();if(g==null)g=d||this.defaultVisible();return g});this._initColor();this._initSize();if(this.isSizeBound)if(a.axes.size.scaleUsesAbs()){this.isSizeAbs=true;var e=this._sceneDefColor;this._sceneDefColor= -function(g,h){return h==="stroke"&&g.vars.size.value<0?u.Color.names.black:e.call(this,g,h)};this.pvMark.lineCap("round").strokeDasharray(function(g){return g.vars.size.value<0?"dash":null})}}).prototype.property("strokeWidth").constructor.add({isColorBound:false,isColorDiscrete:false,isSizeBound:false,isSizeAbs:false,canShow:function(){return!this.scene.isIntermediate},defaultVisible:function(){var a=this.scene;return!a.isNull&&(!this.isSizeBound&&!this.isColorBound||this.isSizeBound&&a.vars.size.value!= -null||this.isColorBound&&(this.isColorDiscrete||a.vars.color.value!=null))},_initColor:function(){var a,b,c=this.panel,d=c.visualRoles.color;if(d){this.isColorDiscrete=d.isDiscrete();c=c.axes.color;if(d.isBound()){this.isColorBound=true;b=c.sceneScale({sceneVarName:"color"})}else if(c)a=c.option("Unbound")}b||(b=f.fun.constant(a||i.defaultColor));this._sceneDefColor=b},_initSize:function(){var a=this.panel,b=a.plot,c=b.option("Shape"),d=b.option("NullShape");b=a.visualRoles.size;var e,g;if(b){var h= -(a=a.axes.size)&&a.scale;if(h&&b.isBound()){this.isSizeBound=true;var j=h.min+(h.max-h.min)*0.05;this.nullSizeShapeHasStrokeOnly=d==="cross";g=function(l){return l.vars.size.value!=null?c:d};e=function(l){l=l.vars.size.value;return l!=null?h(l):d?j:0}}}if(!e){g=f.fun.constant(c);e=function(l){return this.base(l)}}this._sceneDefSize=e;this._sceneDefShape=g},defaultColor:function(a){return this._sceneDefColor(this.scene,a)},normalColor:function(a,b){return b==="stroke"?a.darker():this.base(a,b)},interactiveColor:function(a, -b){var c=this.scene;if(this.mayShowActive(true))switch(b){case "fill":return this.isSizeBound?a.alpha(0.75):a;case "stroke":return a.darker()}else if(this.showsSelection()){var d=c.isSelected();if(!d&&c.anySelected()){if(this.mayShowActive())return a.alpha(0.8);switch(b){case "fill":return this.dimColor(a,b);case "stroke":return a.alpha(0.45)}}if(d&&wa(a)){if(b==="stroke")a=a.darker(3);return a.darker(2)}}if(b==="stroke")return a.darker();return a},defaultSize:function(){return this._sceneDefSize(this.scene)}, -defaultShape:function(){return this._sceneDefShape(this.scene)},interactiveSize:function(a){if(!this.mayShowActive(true))return a;a=Math.sqrt(a);var b=Math.max(1,Math.min(1.1*a,2));return f.sqr(a+b)},defaultStrokeWidth:function(){return this.nullSizeShapeHasStrokeOnly&&this.scene.vars.size.value==null?1.8:1},interactiveStrokeWidth:function(a){return this.mayShowActive(true)?2*a:this.mayShowSelected()?1.5*a:a}});f.type("pvc.visual.Line",i.visual.Sign).init(function(a,b,c){b=b.add(u.Line);this.base(a, -b,c);this.lock("segmented","smart").lock("antialias",true);if(!f.get(c,"freePosition",false)){c=a.isOrientationVertical()?"left":"bottom";this._lockDynamic(a.anchorOrtho(c),"y")._lockDynamic(c,"x")}this._bindProperty("strokeStyle","strokeColor","color")._bindProperty("lineWidth","strokeWidth")}).prototype.property("strokeWidth").constructor.add({_addInteractive:function(a){a=f.setDefaults(a,"noTooltip",true);this.base(a)},y:f.fun.constant(0),x:f.fun.constant(0),defaultStrokeWidth:f.fun.constant(1.5), -interactiveStrokeWidth:function(a){return this.mayShowActive()?Math.max(1,a)*2.5:a},interactiveColor:function(a,b){if(this.mayShowNotAmongSelected())return this.mayShowActive()?u.Color.names.darkgray.darker().darker():this.dimColor(a,b);return this.base(a,b)}});f.type("pvc.visual.Area",i.visual.Sign).init(function(a,b,c){b=b.add(u.Area);c||(c={});c.freeColor=true;this.base(a,b,c);b=f.get(c,"antialias",true);this.lock("segmented","smart").lock("antialias",b);if(!f.get(c,"freePosition",false)){c=a.isOrientationVertical()? -"left":"bottom";b=a.anchorOrtho(c);a=a.anchorOrthoLength(b);this._lockDynamic(c,"x")._lockDynamic(b,"y")._lockDynamic(a,"dy")}this._bindProperty("fillStyle","fillColor","color");this.lock("strokeStyle",null).lock("lineWidth",0)}).add({_addInteractive:function(a){a=f.setDefaults(a,"noTooltip",true);this.base(a)},y:f.fun.constant(0),x:f.fun.constant(0),dy:f.fun.constant(0),interactiveColor:function(a,b){if(b==="fill"&&this.mayShowNotAmongSelected())return this.dimColor(a,b);return this.base(a,b)}}); -f.type("pvc.visual.Bar",i.visual.Sign).init(function(a,b,c){b=b.add(u.Bar);c=f.setDefaults(c,"freeColor",false);this.base(a,b,c);this.normalStroke=f.get(c,"normalStroke",false);this._bindProperty("lineWidth","strokeWidth")}).prototype.property("strokeWidth").constructor.add({normalColor:function(a,b){if(b==="stroke"&&!this.normalStroke)return null;return a},interactiveColor:function(a,b){if(b==="stroke"){if(this.mayShowActive(true))return a.brighter(1.3).alpha(0.7);if(!this.normalStroke)return null; -if(this.mayShowNotAmongSelected()){if(this.mayShowActive())return u.Color.names.darkgray.darker().darker();return this.dimColor(a,b)}if(this.mayShowActive())return a.brighter(1).alpha(0.7)}else if(b==="fill"){if(this.mayShowActive(true))return a.brighter(0.2).alpha(0.8);if(this.mayShowNotAmongSelected()){if(this.mayShowActive())return u.Color.names.darkgray.darker(2).alpha(0.8);return this.dimColor(a,b)}if(this.mayShowActive())return a.brighter(0.2).alpha(0.8)}return this.base(a,b)},defaultStrokeWidth:function(){return 0.5}, -interactiveStrokeWidth:function(a){if(this.mayShowActive(true))return Math.max(1,a)*1.3;return a}});u.PieSlice=function(){u.Wedge.call(this)};u.PieSlice.prototype=u.extend(u.Wedge).property("offsetRadius");u.PieSlice.prototype.midAngle=function(){var a=this.instance();return a.startAngle+a.angle/2};u.PieSlice.prototype.defaults=(new u.PieSlice).extend(u.Wedge.prototype.defaults).offsetRadius(0);f.type("pvc.visual.PieSlice",i.visual.Sign).init(function(a,b,c){b=b.add(u.PieSlice);c=f.setDefaults(c, -"freeColor",false);this.base(a,b,c);this._activeOffsetRadius=f.get(c,"activeOffsetRadius",0);this._maxOffsetRadius=f.get(c,"maxOffsetRadius",0);this._resolvePctRadius=f.get(c,"resolvePctRadius");this._center=f.get(c,"center");this.optional("lineWidth",0.6)._bindProperty("angle","angle")._bindProperty("offsetRadius","offsetRadius")._lockDynamic("bottom","y")._lockDynamic("left","x").lock("top",null).lock("right",null)}).prototype.property("offsetRadius").constructor.add({angle:f.fun.constant(0),x:function(){return this._center.x+ -this._offsetSlice("cos")},y:function(){return this._center.y-this._offsetSlice("sin")},_offsetSlice:function(a){var b=this.pvMark.offsetRadius()||0;if(b)b*=Math[a](this.pvMark.midAngle());return b},defaultColor:function(a){return a==="stroke"?null:this.base(a)},interactiveColor:function(a,b){if(this.mayShowActive(true))switch(b){case "fill":return a.brighter(0.2).alpha(0.8);case "stroke":return a.brighter(1.3).alpha(0.7)}else if(this.mayShowNotAmongSelected())if(b==="fill")return this.dimColor(a, -b);return this.base(a,b)},offsetRadius:function(){var a=this.base();return Math.min(Math.max(0,a),this._maxOffsetRadius)},baseOffsetRadius:function(){var a=this.base()||0;return this._resolvePctRadius(L.parse(a))},interactiveOffsetRadius:function(a){return a+(this.mayShowActive(true)?this._activeOffsetRadius:0)}});f.type("pvc.visual.Rule",i.visual.Sign).init(function(a,b,c){b=b.add(u.Rule);var d=f.get(c,"proto");d&&b.extend(d);this.base(a,b,c);f.get(c,"freeStyle")||this._bindProperty("strokeStyle", -"strokeColor","color")._bindProperty("lineWidth","strokeWidth")}).prototype.property("strokeWidth").constructor.add({_addInteractive:function(a){a=f.setDefaults(a,"noHover",true,"noSelect",true,"noTooltip",true,"noClick",true,"noDoubleClick",true,"showsInteraction",false);this.base(a)},defaultStrokeWidth:function(){return 1},interactiveStrokeWidth:function(a){if(this.mayShowActive(true))return Math.max(1,a)*2.2;return a},interactiveColor:function(a,b){if(this.scene.datum&&!this.mayShowActive(true)&& -this.mayShowNotAmongSelected())return this.dimColor(a,b);return this.base(a,b)}});f.type("pvc.visual.OptionsBase").init(function(a,b,c,d){this.chart=a;this.type=b;this.index=c==null?0:c;this.name=f.get(d,"name");this.id=this._buildId();this.optionId=this._buildOptionId();this._registerResolversFull(this._resolvers=[],d);this.option=i.options(this._getOptionsDefinition(),this)}).add({_buildId:function(){return i.buildIndexedId(this.type,this.index)},_buildOptionId:function(){return this.id},_getOptionsDefinition:f.method({isAbstract:true}), -_chartOption:function(a){return this.chart.options[a]},_registerResolversFull:function(a,b){var c=f.get(b,"fixed");if(c){this._fixed=c;a.push(i.options.specify(function(d){return c[d.name]}))}this._registerResolversNormal(a,b);if(b=f.get(b,"defaults"))this._defaults=b;a.push(this._resolveDefault)},_registerResolversNormal:function(a,b){this.chart.compatVersion()<=1&&a.push(this._resolveByV1OnlyLogic);this.name&&a.push(i.options.specify(function(c){return this._chartOption(this.name+f.firstUpperCase(c.name))})); -a.push(this._resolveByOptionId);f.get(b,"byNaked",!this.index)&&a.push(this._resolveByNaked)},_resolveFull:function(a){for(var b=this._resolvers,c=0,d=b.length;c1){var b=this.role.grouping,c;if(this.scaleType==="discrete")for(c=1;c0)b.splitBandedCenter(b.min,b.max,this.chart.options.panelSizeRatio||0.8)}else b.range(b.min,b.max);return b},getScaleRoundingPaddings:function(){var a=this._roundingPaddings;if(!a){a={begin:0,end:0, -beginLocked:false,endLocked:false};var b=this.scale;if(b&&!b.isNull&&b.type!=="discrete"){var c=this.domain;a.beginLocked=c.minLocked;a.endLocked=c.maxLocked;if(b.type==="numeric"&&this.option("DomainRoundMode")!=="none"){b=b.domain();c=this.domain||f.assert("Original domain must be set");var d=b[1]-b[0];if(d){var e=c[0]-b[0];if(e>0)a.begin=e/d;e=b[1]-c[1];if(e>0)a.end=e/d}}}this._roundingPaddings=a}return a},calcContinuousTicks:function(a){if(a==null)a=this.option("DesiredTickCount");return this.scale.ticks(a, -{roundInside:this.option("DomainRoundMode")!=="tick",numberExponentMin:this.option("TickExponentMin"),numberExponentMax:this.option("TickExponentMax")})},_getOptionsDefinition:function(){return Lb},_buildOptionId:function(){return this.id+"Axis"},_registerResolversNormal:function(a){this.chart.compatVersion()<=1&&a.push(this._resolveByV1OnlyLogic);a.push(this._resolveByOptionId,this._resolveByOrientedId);this.index===1&&a.push(this._resolveByV1OptionId);a.push(this._resolveByScaleType,this._resolveByCommonId)}, -_resolveByOrientedId:i.options.specify(function(a){return this._chartOption(this.orientedId+"Axis"+a.name)}),_resolveByV1OptionId:i.options.specify(function(a){return this._chartOption("secondAxis"+a.name)}),_resolveByScaleType:i.options.specify(function(a){var b=this.scaleType;if(b){a=a.name;var c=this._chartOption(b+"Axis"+a);if(c===undefined&&b!=="discrete")c=this._chartOption("continuousAxis"+a);return c}}),_resolveByCommonId:i.options.specify(function(a){return this._chartOption("axis"+a.name)})}); -da.getOrientation=function(a,b){return a==="base"===(b==="vertical")?"x":"y"};da.getOrientedId=function(a,b){if(b===0)return a;return a+(b+1)};var Y={resolve:"_resolveFull",data:{resolveV1:function(a){!this.index&&this.type==="ortho"&&this._specifyChartOption(a,this.id+a.name);return true}},cast:i.castNumber},Z={resolveV1:function(a){if(this.index){if(this._resolveByV1OptionId(a))return true}else if(this._resolveByOrientedId(a))return true;this._resolveDefault(a);return true}},Mb=i.options.defaultValue(function(){if(!this.typeIndex)return this.orientation=== -"x"?"bottom":"left";var a=this.chart.axesByType[this.type].first.option("Position");return i.BasePanel.oppositeAnchor[a]}),Lb=f.create(ca,{Visible:{resolve:"_resolveFull",data:{resolveV1:function(a){if(this.index<=1){var b=this.index===0?f.firstUpperCase(this.orientation):"Second";this._specifyChartOption(a,"show"+b+"Scale")}return true}},cast:Boolean,value:true},Composite:{resolve:function(a){if(this.index>0){a.specify(false);return true}return this._resolveFull(a)},data:{resolveV1:function(a){this._specifyChartOption(a, -"useCompositeAxis");return true}},cast:Boolean,value:false},Size:{resolve:"_resolveFull",data:Z,cast:Ma},SizeMax:{resolve:"_resolveFull",cast:Ma},Position:{resolve:"_resolveFull",data:{resolveV1:Z.resolveV1,resolveDefault:Mb},cast:Bb},FixedMin:Y,FixedMax:Y,OriginIsZero:{resolve:"_resolveFull",data:{resolveV1:function(a){switch(this.index){case 0:this._specifyChartOption(a,"originIsZero");break;case 1:this.chart._allowV1SecondAxis&&this._specifyChartOption(a,"secondAxisOriginIsZero");break}return true}}, -cast:Boolean,value:true},DomainScope:{resolve:"_resolveFull",cast:Ab,value:"global"},Offset:{resolve:"_resolveFull",data:{resolveV1:function(a){switch(this.index){case 0:this._specifyChartOption(a,"axisOffset");break;case 1:if(this.chart._allowV1SecondAxis){this._specifyChartOption(a,"secondAxisOffset");break}break}return true}},cast:i.castNumber},LabelSpacingMin:{resolve:"_resolveFull",cast:i.castNumber},OverlappedLabelsMode:{resolve:"_resolveFull",cast:i.parseOverlappedLabelsMode,value:"rotatethenhide"}, -Grid:{resolve:"_resolveFull",data:{resolveV1:function(a){this.index||this._specifyChartOption(a,this.orientation+"AxisFullGrid");return true}},cast:Boolean,value:false},GridCrossesMargin:{resolve:"_resolveFull",cast:Boolean,value:true},EndLine:{resolve:"_resolveFull",cast:Boolean},ZeroLine:{resolve:"_resolveFull",cast:Boolean,value:true},RuleCrossesMargin:{resolve:"_resolveFull",cast:Boolean,value:true},Ticks:{resolve:"_resolveFull",cast:Boolean},DesiredTickCount:{resolve:"_resolveFull",data:{resolveV1:Z.resolveV1, -resolveDefault:function(a){if(this.chart.compatVersion()<=1){a.defaultValue(5);return true}}},cast:i.castNumber},MinorTicks:{resolve:"_resolveFull",data:Z,cast:Boolean,value:true},TickFormatter:{resolve:"_resolveFull",cast:f.fun.as},DomainRoundMode:{resolve:"_resolveFull",data:{resolveV1:Z.resolveV1,resolveDefault:function(a){if(this.chart.compatVersion()<=1){a.defaultValue("none");return true}}},cast:i.parseDomainRoundingMode,value:"tick"},TickExponentMin:{resolve:"_resolveFull",cast:i.castNumber}, -TickExponentMax:{resolve:"_resolveFull",cast:i.castNumber},Title:{resolve:"_resolveFull",cast:String},TitleSize:{resolve:"_resolveFull",cast:Na},TitleSizeMax:{resolve:"_resolveFull",cast:Na},TitleFont:{resolve:"_resolveFull",cast:String},TitleMargins:{resolve:"_resolveFull",cast:F.as},TitlePaddings:{resolve:"_resolveFull",cast:F.as},TitleAlign:{resolve:"_resolveFull",cast:function(a){var b=this.option("Position");return i.parseAlign(b,a)}},Font:{resolve:"_resolveFull",cast:String},ClickAction:{resolve:"_resolveFull", -data:Z},DoubleClickAction:{resolve:"_resolveFull",data:Z},TooltipEnabled:{resolve:"_resolveFull",cast:Boolean,value:true},TooltipFormat:{resolve:"_resolveFull",cast:f.fun.as,value:null},TooltipAutoContent:{resolve:"_resolveFull",cast:i.parseTooltipAutoContent,value:"value"}});f.type("pvc.visual.CartesianAxisRootScene",i.visual.Scene);f.type("pvc.visual.CartesianAxisTickScene",i.visual.Scene).init(function(a,b){this.base(a,b);this.vars.tick=new I(f.get(b,"tick"),f.get(b,"tickLabel"),f.get(b,"tickRaw")); -if(f.get(b,"isHidden"))this.isHidden=true}).add({isHidden:false});f.type("pvc.visual.CartesianFocusWindow",i.visual.OptionsBase).init(function(a){this.base(a,"focusWindow",0,{byNaked:false});this.base=new i.visual.CartesianFocusWindowAxis(this,a.axes.base)}).add({_getOptionsDefinition:function(){return Nb},_exportData:function(){return{base:f.copyProps(this.base,i.visual.CartesianFocusWindow.props)}},_importData:function(a){a=a.base;this.base.option.specify({Begin:a.begin,End:a.end,Length:a.length})}, -_initFromOptions:function(){this.base._initFromOptions()},_onAxisChanged:function(){var a=this.option("Changed");a&&a.call(this.chart.basePanel.context())}});var Nb=f.create(ca,{Changed:{resolve:"_resolveFull",cast:f.fun.as}});f.type("pvc.visual.CartesianFocusWindowAxis",i.visual.OptionsBase).init(function(a,b){this.window=a;this.axis=b;this.isDiscrete=b.isDiscrete();this.base(b.chart,"focusWindow"+f.firstUpperCase(b.type),0,{byNaked:false})}).addStatic({props:["begin","end","length"]}).add({_getOptionsDefinition:function(){return Ob}, -_initFromOptions:function(){var a=this.option;this.set({begin:a("Begin"),end:a("End"),length:a("Length")})},set:function(a){var b=this,c=f.get(a,"render"),d=f.get(a,"select",true),e,g,h;if(a=b._readArgs(a)){e=a.begin;g=a.end;h=a.length}else if(this.begin!=null&&this.end!=null&&this.length!=null)return;a=b.axis;var j=a.scale,l=b.isDiscrete;a=!l?a.role.firstDimensionType().cast:null;j=j.domain();var m;if(l){l=j.length;var k,n;if(e!=null){a=+e;if(!isNaN(a))if(a===Infinity){k=l-1;e=j[k]}else if(a===-Infinity){k= -0;e=j[k]}if(k==null){k=j.indexOf(""+e);if(k<0){k=0;e=j[k]}}}if(g!=null){a=+g;if(!isNaN(a))if(a===Infinity){n=l-1;g=j[n]}else if(a===-Infinity){n=0;g=j[n]}if(n==null){n=j.indexOf(""+g);if(n<0){n=l-1;g=j[n]}}}if(h!=null){h=+h;if(isNaN(h))h=null;else if(h<0&&(e!=null||g!=null)){m=e;a=k;e=g;k=n;g=m;n=a;h=-h}}if(e!=null)if(g!=null){if(k>n){m=e;a=k;e=g;k=n;g=m;n=a}h=n-k+1}else{if(h==null)h=l-k;n=k+h-1;if(n>l-1){n=l-1;h=n-k+1}g=j[n]}else if(g!=null){if(h==null)h=n;k=n-h+1;if(k<0){k=0;h=n-k+1}e=j[k]}else{if(h== -null)h=Math.max(~~(l/3),1);if(h>l){h=l;k=0;n=l-1}else{a=~~(l/2);k=a-~~(h/2);n=k+h-1}e=j[k];g=j[n]}}else{if(h!=null){h=+h;if(isNaN(h))h=null;else if(h<0&&(e!=null||g!=null)){m=e;e=g;g=m;h=-h}}k=j[0];n=j[1];l=n-k;if(e!=null){if(en)e=n}if(g!=null){if(gn)g=n}if(e!=null)if(g!=null){if(e>g){m=e;e=g;g=m}h=g-e}else{if(h==null)h=n-e;g=e+h;if(g>n){g=n;h=g-e}}else if(g!=null){if(h==null)h=g-k;e=g-h;if(el){h=l;e=k;g=n}else{m=~~(l/ -2);e=m-~~(h/2);g=+e+ +h}}e=a(e);g=a(g);h=a(h);if(j=b.option("Constraint")){g={type:"new",target:"begin",value:e,length:h,length0:h,min:k,max:n,minView:k,maxView:n};j(g);e=a(g.value);h=a(g.length);g=a(+e+ +h)}}b._set(e,g,h,d,c)},_updatePosition:function(a,b,c,d){var e=this,g=e.axis.scale;if(e.isDiscrete){e=g.invertIndex(a);b=g.invertIndex(b)-1;g=g.domain();a=g[e];g=g[b];e=b-e+1}else{a=g.invert(a);g=g.invert(b);e=g-a}this._set(a,g,e,c,d)},_constraintPosition:function(a){var b=this,c=b.axis,d=c.scale; -if(b.isDiscrete){c=Math.floor(d.invertIndex(a.point,true));if(c>=0){b=d.range();d=d.domain().length;b=(b.max-b.min)/d;if(c>=d&&(a.type==="new"||a.type==="resize-begin"))c=d-1;a.point=c*b}}else if(b=b.option("Constraint")){var e=c.role.firstDimensionType().cast,g=e(d.invert(a.point));c=a.target==="begin"?1:-1;var h=e(d.invert(a.point+c*a.length));h=e(c*(h-g));var j,l;if(a.length===a.length0)j=h;else{l=a.point+c*a.length0;l=e(d.invert(l));j=c*(l-g)}l=e(d.invert(a.min));var m=e(d.invert(a.max));e={type:a.type, -target:a.target,value:g,length:h,length0:j,min:l,max:m,minView:e(d.invert(a.minView)),maxView:e(d.invert(a.maxView))};b(e);if(+e.value!==+g){g=e.value;a.point=d(g)}b=e.length;if(+b!==+h)if(+b===+j)a.length=a.length0;else{b=d(+g+c*+b);a.length=b-c*a.point}if(+e.min!==+l)a.min=d(e.min);if(+e.max!==+m)a.max=d(e.max)}},_compare:function(a,b){return this.isDiscrete?""+a===""+b:+a===+b},_set:function(a,b,c,d,e){var g=this,h=false;if(!g._compare(a,g.begin)){g.begin=a;h=true}if(!g._compare(b,g.end)){g.end= -b;h=true}if(!g._compare(c,g.length)){g.length=c;h=true}h&&g.window._onAxisChanged(this);d&&g._updateSelection({render:e});return h},_readArgs:function(a){if(a){var b={},c=0;i.visual.CartesianFocusWindowAxis.props.forEach(function(d){var e=a[d];if(e!=null)c=true;else e=this[d];b[d]=e},this);if(c)return b}},_updateSelection:function(a){var b=this,c,d=b.axis,e=d.isDiscrete(),g=d.chart,h=d.dataCell;d=h.role;h=g.partData(h.dataPartValue,{visible:true});var j;if(e){j=d.flatten(h);d=j._childrenByKey[b.begin]; -e=j._childrenByKey[b.end];if(d&&e){c=d.childIndex();e=e.childIndex();c=f.range(c,e-c+1).select(function(m){return j._children[m]}).selectMany(function(m){return m._datums}).distinct(function(m){return m.key})}}else{j=h;var l=d.firstDimensionName();c=f.query(h._datums).where(function(m){m=m.atoms[l].value;return m!=null&&m>=b.begin&&m<=b.end})}if(c){g.data.replaceSelected(c);g.root.updateSelections(a)}}});var Ob=f.create(ca,{Resizable:{resolve:"_resolveFull",cast:Boolean,value:true},Movable:{resolve:"_resolveFull", -cast:Boolean,value:true},Begin:{resolve:"_resolveFull"},End:{resolve:"_resolveFull"},Length:{resolve:"_resolveFull"},Constraint:{resolve:"_resolveFull",cast:f.fun.as}});f.type("pvc.visual.ColorAxis",ua).add({scaleNullRangeValue:function(){return this.option("Missing")||null},scaleUsesAbs:function(){return this.option("UseAbs")},bind:function(a){this.base(a);this._plotList=f.query(a).select(function(b){return b.plot}).distinct(function(b){return b&&b.id}).array();return this},_wrapScale:function(a){if(this.scaleType=== -"discrete"?this.option.isSpecified("Transform")||!this.option.isSpecified("Colors")&&!this.option.isSpecified("Map"):true){var b=this.option("Transform");if(b)a=a.transform(b)}return this.base(a)},scheme:function(){return f.lazy(this,"_scheme",this._createScheme,this)},_createColorMapFilter:function(a){var b=f.uniqueIndex(a,function(c){return c.key});return{domain:function(c){return!f.hasOwn(a,c)},color:function(c){return!f.hasOwn(b,c.key)}}},_createScheme:function(){var a=this,b=a.option("Colors"); -if(a.scaleType!=="discrete")return function(){var e=b.apply(null,arguments);return a._wrapScale(e)};var c=a.option("Map");if(!c)return function(){var e=b.apply(null,arguments);return a._wrapScale(e)};var d=this._createColorMapFilter(c);return function(e){var g;e instanceof Array||(e=f.array.copy(arguments));e=e.filter(d.domain);var h=b(e);g=h.range().filter(d.color);h.range(g);g=function(m){return f.getOwn(c,m)||h(m)};f.copy(g,h);var j,l;g.domain=function(){if(arguments.length)throw f.operationInvalid("The scale cannot be modified."); -j||(j=f.array.append(f.ownKeys(c),e));return j};g.range=function(){if(arguments.length)throw f.operationInvalid("The scale cannot be modified.");l||(l=f.array.append(f.own(c),e));return l};return a._wrapScale(g)}},sceneScale:function(a){var b=f.get(a,"sceneVarName")||this.role.name,c=this.scalesByCateg;if(c){var d=this.option("Missing");return function(e){var g=e.vars[b].value;if(g==null)return d;return c[e.group.parent.absKey](g)}}return this.scale.by1(function(e){return e&&e.vars[b].value})},_buildOptionId:function(){return this.id+ -"Axis"},_getOptionsDefinition:function(){return Pb},_resolveByNaked:i.options.specify(function(a){if(!this.index)return this._chartOption(this.id+f.firstUpperCase(a.name))}),_specifyV1ChartOption:function(a,b){if(!this.index&&this.chart.compatVersion()<=1&&this._specifyChartOption(a,b))return true}});Y={resolveDefault:function(a){if(!this.index&&this._specifyChartOption(a,f.firstLowerCase(a.name)))return true}};var ra,Pb=f.create(ca,{Colors:{resolve:"_resolveFull",getDefault:Db,data:{resolveV1:function(a){if(this.scaleType=== -"discrete")if(this.index===0)this._specifyChartOption(a,"colors");else this.index===1&&this.chart._allowV1SecondAxis&&this._specifyChartOption(a,"secondAxisColor");else this._specifyChartOption(a,"colorRange");return true},resolveDefault:function(a){this.index===0&&this._specifyChartOption(a,"colors")}},cast:i.colorScheme},Map:{resolve:"_resolveFull",cast:Cb},Transform:{resolve:"_resolveFull",data:{resolveDefault:function(a){var b=this._plotList;if(b.length<=2)if(f.query(b).all(function(c){c=c.name; -return c==="plot2"||c==="trend"})){a.defaultValue(i.brighterColorTransform);return true}}},cast:f.fun.to},NormByCategory:{resolve:function(a){if(!this.chart._allowColorPerCategory){a.specify(false);return true}return this._resolveFull(a)},data:{resolveV1:function(a){this._specifyV1ChartOption(a,"normPerBaseCategory");return true}},cast:Boolean,value:false},ScaleType:{resolve:"_resolveFull",data:{resolveV1:function(a){this._specifyV1ChartOption(a,"scalingType");return true}},cast:i.parseContinuousColorScaleType, -value:"linear"},UseAbs:{resolve:"_resolveFull",cast:Boolean,value:false},Domain:{resolve:"_resolveFull",data:{resolveV1:function(a){this._specifyV1ChartOption(a,"colorRangeInterval");return true}},cast:f.array.to},Min:{resolve:"_resolveFull",data:{resolveV1:function(a){this._specifyV1ChartOption(a,"minColor");return true}},cast:u.color},Max:{resolve:"_resolveFull",data:{resolveV1:function(a){this._specifyV1ChartOption(a,"maxColor");return true}},cast:u.color},Missing:{resolve:"_resolveFull",data:{resolveV1:function(a){this._specifyV1ChartOption(a, -"nullColor");return true}},cast:u.color,value:u.color("lightgray")},Unbound:{resolve:"_resolveFull",getDefault:function(){return this.option("Colors")().range()[0]||i.defaultColor},cast:u.color},LegendVisible:{resolve:"_resolveFull",data:Y,cast:Boolean,value:true},LegendClickMode:{resolve:"_resolveFull",data:Y,cast:i.parseLegendClickMode,value:"togglevisible"},LegendDrawLine:{resolve:"_resolveFull",data:Y,cast:Boolean,value:false},LegendDrawMarker:{resolve:"_resolveFull",data:Y,cast:Boolean,value:true}, -LegendShape:{resolve:"_resolveFull",data:Y,cast:i.parseShape}});f.type("pvc.visual.SizeAxis",ua).init(function(a,b,c,d){d=f.set(d,"byNaked",false);this.base(a,b,c,d)}).add({_buildOptionId:function(){return this.id+"Axis"},scaleTreatsNullAs:function(){return"min"},scaleUsesAbs:function(){return this.option("UseAbs")},setScaleRange:function(a){var b=this.scale;b.min=a.min;b.max=a.max;b.size=a.max-a.min;b.range(b.min,b.max);i.debug>=4&&i.log("Scale: "+i.stringify(f.copyOwn(b)));return this},_getOptionsDefinition:function(){return Qb}}); -var Qb=f.create(ca,{OriginIsZero:{resolve:"_resolveFull",cast:Boolean,value:false},FixedMin:{resolve:"_resolveFull",cast:i.castNumber},FixedMax:{resolve:"_resolveFull",cast:i.castNumber},UseAbs:{resolve:"_resolveFull",cast:Boolean,value:false}});f.type("pvc.visual.Legend",i.visual.OptionsBase).init(function(a,b,c,d){d=f.set(d,"byNaked",false);this.base(a,b,c,d)}).add({_getOptionsDefinition:function(){return Rb}});var Rb={Position:{resolve:"_resolveFull",cast:i.parsePosition,value:"bottom"},Size:{resolve:"_resolveFull", -cast:Oa},SizeMax:{resolve:"_resolveFull",cast:Oa},Align:{resolve:"_resolveFull",data:{resolveDefault:function(a){var b=this.option("Position"),c;if(b!=="top"&&b!=="bottom")c="top";else if(this.chart.compatVersion()<=1)c="left";a.defaultValue(c);return true}},cast:Eb},Margins:{resolve:"_resolveFull",data:{resolveDefault:function(a){if(this.chart.compatVersion()>1){var b=this.option("Position");b=f.set({},i.BasePanel.oppositeAnchor[b],5);a.defaultValue(b)}return true}},cast:F.as},Paddings:{resolve:"_resolveFull", -cast:F.as,value:5},Font:{resolve:"_resolveFull",cast:String,value:"10px sans-serif"}};f.type("pvc.visual.legend.BulletRootScene",i.visual.Scene).init(function(a,b){this.base(a,b);a=f.get(b,"markerSize",15);var c=(new F(f.get(b,"itemPadding",5))).resolve(a,a);f.set(this.vars,"horizontal",f.get(b,"horizontal",false),"font",f.get(b,"font"),"markerSize",a,"textMargin",f.get(b,"textMargin",6),"itemPadding",c)}).add({layout:function(a){function b(q){var s=q.labelTextSize(),r=!s||!s.width||!s.height;q.isHidden= -r;if(!r){s={width:h+s.width+0,height:Math.max(s.height,g)};var t;if(n)t=!n.items.length;else{n=new i.visual.legend.BulletItemSceneRow(0);t=true}r=n.size.width+s[l];t||(r+=j[l]);if(!t&&r>k){c(false);r=s[l]}t=n.size;t.width=r;t.height=Math.max(t.height,s[m]);r=n.items.length;n.items.push(q);f.set(q.vars,"row",n,"rowIndex",r,"clientSize",s)}}function c(q){var s=n.size;p.height+=s.height;if(o.length)p.height+=j[m];p.width=Math.max(p.width,s.width);o.push(n);q||(n=new i.visual.legend.BulletItemSceneRow(o.length))} -var d=a.clientSize;if(!(d.width>0&&d.height>0))return new M(0,0);var e=a.desiredClientSize,g=this.vars.markerSize,h=g+this.vars.textMargin,j=this.vars.itemPadding,l=this.vars.horizontal?"width":"height",m=i.BasePanel.oppositeLength[l],k=e[l];if(!k||k<0)k=d[l];var n,o=[],p={width:0,height:0};this.childNodes.forEach(function(q){q.childNodes.forEach(b,this)},this);if(!n)return new M(0,0);c(true);f.set(this.vars,"rows",o,"rowCount",n,"size",p);a=this.compatVersion()<=1?k:p.width;e=e[m];if(!e||e<0)e=p.height; -return f.set({},l,Math.min(a,d[l]),m,Math.min(e,d[m]))},defaultGroupSceneType:function(){var a=this._bulletGroupType;if(!a)this._bulletGroupType=a=f.type(i.visual.legend.BulletGroupScene);return a},createGroup:function(a){return new (this.defaultGroupSceneType())(this,a)}});f.type("pvc.visual.legend.BulletItemSceneRow").init(function(a){this.index=a;this.items=[];this.size={width:0,height:0}});f.type("pvc.visual.legend.BulletGroupScene",i.visual.Scene).init(function(a,b){this.base(a,b);this.extensionPrefix= -f.get(b,"extensionPrefix")||"";this._renderer=f.get(b,"renderer");this.colorAxis=f.get(b,"colorAxis");this.clickMode=f.get(b,"clickMode");if(!this.clickMode&&this.colorAxis)this.clickMode=this.colorAxis.option("LegendClickMode")}).add({hasRenderer:function(){return!!this._renderer},renderer:function(a){if(a!=null)this._renderer=a;else{a=this._renderer;if(!a){var b;if(a=this.colorAxis)b={drawRule:a.option("LegendDrawLine"),drawMarker:a.option("LegendDrawMarker"),markerShape:a.option("LegendShape")}; -this._renderer=a=new i.visual.legend.BulletItemDefaultRenderer(b)}}return a},itemSceneType:function(){var a=this._itemSceneType;if(!a){a=f.type(i.visual.legend.BulletItemScene);switch(this.clickMode){case "toggleselected":a.add(i.visual.legend.BulletItemSceneSelection);break;case "togglevisible":a.add(i.visual.legend.BulletItemSceneVisibility);break}var b=this.panel();b._extendSceneType("item",a,["isOn","executable","execute","value"]);var c=i.makeExtensionAbsId(i.makeExtensionAbsId("ItemScene",[this.extensionPrefix, -"$"]),b._getExtensionPrefix());b=b.chart._getExtension(c,"value");b!==undefined&&a.prototype.variable("value",b);this._itemSceneType=a}return a},createItem:function(a){return new (this.itemSceneType())(this,a)}});f.type("pvc.visual.legend.BulletItemScene",i.visual.Scene).init(function(){this.base.apply(this,arguments);if(!this.executable()){var a=i.visual.Interactive;this._ibits=a.Interactive|a.ShowsInteraction|a.Hoverable|a.SelectableAny}}).add({isOn:f.fun.constant(true),executable:f.fun.constant(false), -execute:f.fun.constant(),labelTextSize:function(){return u.Text.measure(this.value().label,this.vars.font)},_valueEval:function(){var a=this._valueEvalCore();a instanceof I||(a=new I(a,a));return a},_valueEvalCore:function(){var a,b,c,d=this.group||this.datum;if(d){a=d.value;b=d.rawValue;c=d.ensureLabel()+this._getTrendLineSuffix(d)}return new I(a||null,c||"",b)},_getTrendLineSuffix:function(a){var b=this.chart()._getDataPartDimName();if(b){a=a.atoms[b];if(isNaN(+a.value))return" ("+a.label+")"}return""}}).prototype.variable("value"); -f.type("pvc.visual.legend.BulletItemSceneSelection").add({isOn:function(){return!(this.group||this.datum).owner.selectedCount()||this.isSelected()},executable:function(){return this.chart().selectableByClick()},execute:function(){var a=this.datums().array();if(a.length){var b=this.chart();b._updatingSelections(function(){(a=b._onUserSelection(a))&&a.length&&i.data.Data.toggleSelected(a,true)})}}});f.type("pvc.visual.legend.BulletItemSceneVisibility").add({isOn:function(){return this.datums().any(function(a){return!a.isNull&& -a.isVisible})},executable:f.fun.constant(true),execute:function(){i.data.Data.toggleVisible(this.datums())&&this.chart().render(true,true,false)}});f.type("pvc.visual.legend.BulletItemRenderer");f.type("pvc.visual.legend.BulletItemDefaultRenderer",i.visual.legend.BulletItemRenderer).init(function(a){if(this.drawRule=f.get(a,"drawRule",false))this.rulePvProto=f.get(a,"rulePvProto");if(this.drawMarker=!this.drawRule||f.get(a,"drawMarker",true)){this.markerShape=f.get(a,"markerShape","square");this.markerPvProto= -f.get(a,"markerPvProto")}}).add({drawRule:false,drawMarker:true,markerShape:null,rulePvProto:null,markerPvProto:null,create:function(a,b,c,d){var e={},g=this.drawRule,h=function(m){return m.color};if(g){var j=(new O).left(0).top(function(){return this.parent.height()/2}).width(function(){return this.parent.width()}).lineWidth(1,i.extensionTag).strokeStyle(h,i.extensionTag),l=this.rulePvProto;if(l)j=l.extend(j);e.pvRule=(new i.visual.Rule(a,b,{proto:j,noSelect:false,noHover:false,activeSeriesAware:false, -extensionId:c+"Rule",showsInteraction:true,wrapper:d})).pvMark}if(this.drawMarker){g=(new O).left(function(){return this.parent.width()/2}).top(function(){return this.parent.height()/2}).shapeSize(function(){return this.parent.width()},i.extensionTag).lineWidth(2,i.extensionTag).fillStyle(h,i.extensionTag).strokeStyle(h,i.extensionTag).shape(this.markerShape,i.extensionTag).angle(g?0:Math.PI/2,i.extensionTag).antialias(function(){var m=Math.abs(Math.cos(this.angle()));if(m!==0&&m!==1)switch(this.shape()){case "square":case "bar":return false}return true}, -i.extensionTag);if(h=this.markerPvProto)g=h.extend(g);e.pvDot=(new i.visual.Dot(a,b,{proto:g,freePosition:true,activeSeriesAware:false,noTooltip:true,noClick:true,extensionId:c+"Dot",wrapper:d})).pvMark}return e}});f.type("pvc.visual.DataCell").init(function(a,b,c,d,e){this.plot=a;this.axisType=b;this.axisIndex=c;this.role=a.chart.visualRoles[d];this.dataPartValue=e}).add({isBound:function(){return this.role&&this.role.isBound()},domainData:function(){return f.lazy(this,"_domainData",this._resolveDomainData, -this)},domainItemDatas:function(){var a=this.domainData();return f.query((a||undefined)&&a.children())},domainItemDataValue:function(a){return f.nullyTo(a.value,"")},domainItemValues:function(){return this.domainItemDatas().select(this.domainItemDataValue,this).distinct()},_resolveDomainData:function(){var a=this.role;if(a&&a.isBound()){var b=this.plot.chart.partData(this.dataPartValue);if(b)return a.flatten(b)}return null}});f.type("pvc.visual.Plot",i.visual.OptionsBase).init(function(a,b){var c= -f.getPath(a,["plotsByType",this.type]);c=c?c.length:0;b=f.set(b,"byNaked",!a.plotList.length);this.base(a,this.type,c,b);a._addPlot(this);a=this.extensionPrefixes=[this.id];this.globalIndex||a.push("");this.name&&a.push(this.name)}).add({_getOptionsDefinition:function(){return i.visual.Plot.optionsDef},_resolveByNaked:i.options.specify(function(a){if(!this.globalIndex)return this._chartOption(f.firstLowerCase(a.name))}),collectDataCells:function(a){var b=this._getColorDataCell();b&&a.push(b)},_getColorDataCell:function(){var a= -this.option("ColorRole");if(a)return new i.visual.DataCell(this,"color",this.option("ColorAxis")-1,a,this.option("DataPart"))}});i.visual.Plot.optionsDef={Orientation:{resolve:function(a){a.specify(this._chartOption("orientation")||"vertical");return true},cast:String},ValuesVisible:{resolve:"_resolveFull",data:{resolveV1:function(a){if(this.globalIndex===0){var b=this._chartOption("showValues");if(b!==undefined)a.specify(b);else{b=this.type!=="point";a.defaultValue(b)}return true}}},cast:Boolean, -value:false},ValuesAnchor:{resolve:"_resolveFull",cast:i.parseAnchor},ValuesFont:{resolve:"_resolveFull",cast:String,value:"10px sans-serif"},ValuesMask:{resolve:"_resolveFull",cast:String,value:"{value}"},ValuesOptimizeLegibility:{resolve:"_resolveFull",cast:Boolean,value:false},DataPart:{resolve:"_resolveFixed",cast:String,value:"0"},ColorRole:{resolve:"_resolveFixed",cast:String,value:"color"},ColorAxis:{resolve:i.options.resolvers([function(a){if(this.globalIndex===0){a.specify(1);return true}}, -"_resolveFull"]),cast:function(a){a=i.castNumber(a);return a=a!=null?f.between(a,1,10):1},value:1}};f.type("pvc.visual.CartesianPlot",i.visual.Plot).add({_getOptionsDefinition:function(){return i.visual.CartesianPlot.optionsDef}});i.visual.CartesianPlot.optionsDef=f.create(i.visual.Plot.optionsDef,{BaseAxis:{value:1},BaseRole:{resolve:"_resolveFixed",cast:String},OrthoAxis:{resolve:function(a){if(this.globalIndex===0){a.specify(1);return true}return this._resolveFull(a)},data:{resolveV1:function(a){this.name=== -"plot2"&&this.chart._allowV1SecondAxis&&this._chartOption("secondAxisIndependentScale")&&a.specify(2);return true}},cast:function(a){a=i.castNumber(a);return a=a!=null?f.between(a,1,10):1},value:1},OrthoRole:{resolve:i.options.resolvers(["_resolveFixed","_resolveDefault"])},Trend:{resolve:"_resolveFull",data:{resolveDefault:function(a){var b=this.option("TrendType");if(b){a.defaultValue({type:b});return true}}},cast:Fb},TrendType:{resolve:"_resolveFull",cast:i.parseTrendType},TrendLabel:{resolve:"_resolveFull", -cast:String},NullInterpolationMode:{resolve:"_resolveFull",cast:i.parseNullInterpolationMode,value:"none"}});f.type("pvc.visual.CategoricalPlot",i.visual.CartesianPlot).add({_getOptionsDefinition:function(){return i.visual.CategoricalPlot.optionsDef}});i.visual.CategoricalPlot.optionsDef=f.create(i.visual.CartesianPlot.optionsDef,{Stacked:{resolve:"_resolveFull",cast:Boolean,value:false},BaseRole:{value:"category"},OrthoRole:{value:"value"}});f.type("pvc.visual.BarPlotAbstract",i.visual.CategoricalPlot).add({_getOptionsDefinition:function(){return i.visual.BarPlotAbstract.optionsDef}}); -i.visual.BarPlotAbstract.optionsDef=f.create(i.visual.CategoricalPlot.optionsDef,{BarSizeRatio:{resolve:"_resolveFull",cast:function(a){a=i.castNumber(a);if(a==null)a=1;else if(a<0.05)a=0.05;else if(a>1)a=1;return a},value:0.9},BarSizeMax:{resolve:"_resolveFull",data:{resolveV1:function(a){this._specifyChartOption(a,"maxBarSize");return true}},cast:function(a){a=i.castNumber(a);if(a==null)a=Infinity;else if(a<1)a=1;return a},value:2E3},BarStackedMargin:{resolve:"_resolveFull",cast:function(a){a=i.castNumber(a); -if(a!=null&&a<0)a=0;return a},value:0},OverflowMarkersVisible:{resolve:"_resolveFull",cast:Boolean,value:true},ValuesAnchor:{value:"center"}});f.type("pvc.visual.BarPlot",i.visual.BarPlotAbstract).add({type:"bar"});f.type("pvc.visual.NormalizedBarPlot",i.visual.BarPlotAbstract).add({type:"bar",_getOptionsDefinition:function(){return i.visual.NormalizedBarPlot.optionsDef}});i.visual.NormalizedBarPlot.optionsDef=f.create(i.visual.BarPlotAbstract.optionsDef,{Stacked:{resolve:null,value:true}});f.type("pvc.visual.WaterfallPlot", -i.visual.BarPlotAbstract).add({type:"water",_getOptionsDefinition:function(){return i.visual.WaterfallPlot.optionsDef}});i.visual.WaterfallPlot.optionsDef=f.create(i.visual.BarPlotAbstract.optionsDef,{Stacked:{resolve:null,value:true},TotalLineLabel:{resolve:"_resolveFull",cast:String,value:"Accumulated"},TotalValuesVisible:{resolve:"_resolveFull",data:{resolveDefault:function(a){a.defaultValue(this.option("ValuesVisible"));return true}},cast:Boolean},Direction:{resolve:"_resolveFull",cast:i.parseWaterDirection, -value:"down"},AreasVisible:{resolve:"_resolveFull",cast:Boolean,value:true},AllCategoryLabel:{resolve:"_resolveFull",cast:String,value:"All"}});f.type("pvc.visual.PointPlot",i.visual.CategoricalPlot).add({type:"point",_getOptionsDefinition:function(){return i.visual.PointPlot.optionsDef}});i.visual.PointPlot.optionsDef=f.create(i.visual.CategoricalPlot.optionsDef,{DotsVisible:{resolve:"_resolveFull",data:sa("Dots",true),cast:Boolean,value:false},LinesVisible:{resolve:"_resolveFull",data:sa("Lines", -true),cast:Boolean,value:false},AreasVisible:{resolve:"_resolveFull",data:sa("Areas",false),cast:Boolean,value:false},ValuesAnchor:{value:"right"}});f.type("pvc.visual.MetricXYPlot",i.visual.CartesianPlot).add({_getOptionsDefinition:function(){return i.visual.MetricXYPlot.optionsDef}});i.visual.MetricXYPlot.optionsDef=f.create(i.visual.CartesianPlot.optionsDef,{BaseRole:{value:"x"},OrthoAxis:{resolve:null},OrthoRole:{value:"y"}});f.type("pvc.visual.MetricPointPlot",i.visual.MetricXYPlot).add({type:"scatter", -_getOptionsDefinition:function(){return i.visual.MetricPointPlot.optionsDef}});i.visual.MetricPointPlot.optionsDef=f.create(i.visual.MetricXYPlot.optionsDef,{SizeRole:{resolve:"_resolveFixed",value:"size"},SizeAxis:{resolve:"_resolveFixed",value:1},Shape:{resolve:"_resolveFull",cast:i.parseShape,value:"circle"},NullShape:{resolve:"_resolveFull",cast:i.parseShape,value:"cross"},DotsVisible:{resolve:"_resolveFull",data:Pa("Dots"),cast:Boolean,value:false},LinesVisible:{resolve:"_resolveFull",data:Pa("Lines"), -cast:Boolean,value:false},ValuesAnchor:{value:"right"},ValuesMask:{value:"{x},{y}"}});f.type("pvc.visual.PiePlot",i.visual.Plot).add({type:"pie",_getOptionsDefinition:function(){return i.visual.PiePlot.optionsDef}});i.visual.PiePlot.optionsDef=f.create(i.visual.Plot.optionsDef,{ActiveSliceRadius:{resolve:"_resolveFull",cast:L.parse,value:new L(0.05)},ExplodedSliceRadius:{resolve:"_resolveFull",cast:L.parse,value:0},ExplodedSliceIndex:{resolve:"_resolveFull",cast:i.castNumber,value:null},ValuesAnchor:{cast:i.parseAnchorWedge, -value:"outer"},ValuesVisible:{value:true},ValuesLabelStyle:{resolve:function(a){if(this.chart.compatVersion()<=1){a.specify("inside");return true}return this._resolveFull(a)},cast:function(a){switch(a){case "inside":case "linked":return a}i.debug>=2&&i.log("[Warning] Invalid 'ValuesLabelStyle' value: '"+a+"'.");return"linked"},value:"linked"},ValuesMask:{resolve:"_resolveFull",data:{resolveDefault:function(a){a.defaultValue(this.option("ValuesLabelStyle")==="linked"?"{value} ({value.percent})":"{value}"); -return true}}},LinkInsetRadius:{resolve:"_resolveFull",cast:L.parse,value:new L(0.05)},LinkOutsetRadius:{resolve:"_resolveFull",cast:L.parse,value:new L(0.025)},LinkMargin:{resolve:"_resolveFull",cast:L.parse,value:new L(0.025)},LinkHandleWidth:{resolve:"_resolveFull",cast:i.castNumber,value:0.5},LinkLabelSize:{resolve:"_resolveFull",cast:L.parse,value:new L(0.15)},LinkLabelSpacingMin:{resolve:"_resolveFull",cast:i.castNumber,value:0.5}});f.type("pvc.visual.HeatGridPlot",i.visual.CategoricalPlot).add({type:"heatGrid", -_getOptionsDefinition:function(){return i.visual.HeatGridPlot.optionsDef}});i.visual.HeatGridPlot.optionsDef=f.create(i.visual.CategoricalPlot.optionsDef,{SizeRole:{value:"size"},SizeAxis:{value:1},UseShapes:{resolve:"_resolveFull",cast:Boolean,value:false},Shape:{resolve:"_resolveFull",cast:i.parseShape,value:"square"},NullShape:{resolve:"_resolveFull",cast:i.parseShape,value:"cross"},ValuesVisible:{getDefault:function(){return!this.option("UseShapes")},value:null},ValuesMask:{value:null},ValuesAnchor:{value:"center"}, -OrthoRole:{value:"series"},OrthoAxis:{resolve:null},NullInterpolationMode:{resolve:null,value:"none"},Stacked:{resolve:null,value:false}});f.type("pvc.visual.BoxPlot",i.visual.CategoricalPlot).add({type:"box",_getOptionsDefinition:function(){return i.visual.BoxPlot.optionsDef}});i.visual.BoxPlot.optionsDef=f.create(i.visual.CategoricalPlot.optionsDef,{Stacked:{resolve:null,value:false},OrthoRole:{value:["median","lowerQuartil","upperQuartil","minimum","maximum"]},BoxSizeRatio:{resolve:"_resolveFull", -cast:function(a){a=i.castNumber(a);if(a==null)a=1;else if(a<0.05)a=0.05;else if(a>1)a=1;return a},value:1/3},BoxSizeMax:{resolve:"_resolveFull",data:{resolveV1:function(a){this._specifyChartOption(a,"maxBoxSize");return true}},cast:function(a){a=i.castNumber(a);if(a==null)a=Infinity;else if(a<1)a=1;return a},value:Infinity}});f.type("pvc.visual.BulletPlot",i.visual.Plot).add({type:"bullet",_getOptionsDefinition:function(){return i.visual.BulletPlot.optionsDef}});i.visual.BulletPlot.optionsDef=f.create(i.visual.Plot.optionsDef, -{ValuesVisible:{value:true},ColorRole:{value:null}});f.type("pvc.visual.TreemapColorDataCell",i.visual.DataCell).init(function(){this.base.apply(this,arguments);var a=this.role.grouping;this._valueProp=!a||a.isSingleDimension?"value":"absKey"}).add({domainItemDatas:function(){var a=this.domainData();a=f.query((a||undefined)&&a.nodes());if(this.plot.option("ColorMode")==="byparent")return a.where(function(b){return(!b.parent||b.value!=null)&&b.children().any(function(c){return c.value!=null&&c.children().prop("value").all(f.nully)})}); -return a.where(function(b){if(!b.childCount())return!b.parent||b.value!=null;return b.value!=null&&!b.children().prop("value").any(f.notNully)})},domainItemDataValue:function(a){return f.nullyTo(a[this._valueProp],"")},_resolveDomainData:function(){var a=this.role;if(a&&a.isBound()){var b=this.plot.chart.partData(this.dataPartValue);if(b)return a.select(b)}return null}});f.type("pvc.visual.TreemapPlot",i.visual.Plot).add({type:"treemap",_getOptionsDefinition:function(){return i.visual.TreemapPlot.optionsDef}, -collectDataCells:function(a){this.base(a);var b=this.option("SizeRole");b&&a.push(new i.visual.DataCell(this,"size",this.option("SizeAxis")-1,b,this.option("DataPart")))},_getColorDataCell:function(){var a=this.option("ColorRole");if(a)return new i.visual.TreemapColorDataCell(this,"color",this.option("ColorAxis")-1,a,this.option("DataPart"))}});i.visual.TreemapPlot.optionsDef=f.create(i.visual.Plot.optionsDef,{SizeRole:{resolve:"_resolveFixed",value:"size"},SizeAxis:{resolve:"_resolveFixed",value:1}, -ValuesAnchor:{cast:i.parseAnchor,value:"center"},ValuesVisible:{value:true},ValuesMask:{resolve:"_resolveFull",value:"{category}"},ValuesOptimizeLegibility:{value:true},LayoutMode:{resolve:"_resolveFull",cast:i.parseTreemapLayoutMode,value:"squarify"},ColorMode:{resolve:"_resolveFull",cast:i.parseTreemapColorMode,value:"byparent"},RootCategoryLabel:{resolve:"_resolveFull",cast:String,value:"All"}});f.type("pvc.Abstract").init(function(){this._syncLog()}).add({invisibleLineWidth:0.001,defaultLineWidth:1.5, -_logInstanceId:null,_syncLog:function(){if(i.debug&&typeof console!=="undefined"){var a=this._getLogInstanceId();["log","info",["trace","debug"],"error","warn",["group","groupCollapsed"],"groupEnd"].forEach(function(b){b=b instanceof Array?b:[b,b];va(this,"_"+b[0],b[1],a)},this)}},_getLogInstanceId:function(){return this._logInstanceId||(this._logInstanceId=this._processLogInstanceId(this._createLogInstanceId()))},_createLogInstanceId:function(){return""+this.constructor},_processLogInstanceId:function(a){a= -a.substr(0,30);if(a.length<30)a+=f.array.create(30-a.length," ").join("");return"["+a+"]"}});f.scope(function(){var a=i.Abstract.prototype,b=function(){this._syncLog()};["log","info","trace","error","warn","group","groupEnd"].forEach(function(c){a["_"+c]=b})});f.type("pvc.BaseChart",i.Abstract).add(i.visual.Interactive).init(function(a){var b=a,c=this.parent=f.get(a,"parent")||null;if(c)a||f.fail.argumentRequired("options");else a=f.mixin.copy({},this.defaults,a);this.options=a;if(c){this.root=c.root; -this.smallColIndex=a.smallColIndex;this.smallRowIndex=a.smallRowIndex}else this.root=this;this.base();i.debug>=3&&this._info("NEW CHART\n"+i.logSeparator.replace(/-/g,"=")+"\n DebugLevel: "+i.debug);if(i.debug>=3&&!c&&b){this._info("OPTIONS:\n",b);i.debug>=5&&this._trace(i.stringify(a,{ownOnly:false,funs:true}))}c&&c._addChild(this);this._constructData(a);this._constructVisualRoles(a)}).add({_disposed:false,_animatable:false,parent:null,children:null,root:null,isPreRendered:false,_createVersion:0, -renderCallback:undefined,multiChartPageCount:null,multiChartPageIndex:null,left:0,top:0,width:null,height:null,margins:null,paddings:null,_allowV1SecondAxis:false,compatVersion:function(a){return(a||this.options).compatVersion},_createLogInstanceId:function(){return""+this.constructor+this._createLogChildSuffix()},_createLogChildSuffix:function(){return this.parent?" ("+(this.smallRowIndex+1)+","+(this.smallColIndex+1)+")":""},_addChild:function(a){a.parent===this||f.assert("Not a child of this chart."); -this.children.push(a)},_preRender:function(a){this._preRenderPhase1(a);this._preRenderPhase2(a)},_preRenderPhase1:function(a){this._createVersion++;this.isPreRendered=false;i.debug>=3&&this._log("Prerendering");this.children=[];this.parent||i.removeTipsyLegends();this._processOptions();this._checkNoDataI();if(!this.parent&&!this.data){this._initVisualRoles();this._bindVisualRolesPreI();this._complexTypeProj=this._createComplexTypeProject();this._bindVisualRolesPreII()}this._initData(a);this._checkNoDataII(); -a=this.visualRoles.multiChart.isBound();this._initPlots(a);this._initAxes(a);this._bindAxes(a);if(this.parent||!a){this._interpolate(a);this._generateTrends(a)}this._setAxesScales(a)},_preRenderPhase2:function(){this._initChartPanels(this.visualRoles.multiChart.isBound());this.isPreRendered=true},_setSmallLayout:function(a){if(a){var b=this.basePanel;this._setProp("left",a)|this._setProp("top",a)&&b&&f.set(b.position,"left",this.left,"top",this.top);if(this._setProp("width",a)|this._setProp("height", -a))if(b)b.size=new M(this.width,this.height);if(this._setProp("margins",a)&&b)b.margins=new F(this.margins);if(this._setProp("paddings",a)&&b)b.paddings=new F(this.paddings)}},_setProp:function(a,b){b=b[a];if(b!=null){this[a]=b;return true}},_processOptions:function(){var a=this.options;if(!this.parent){this.width=a.width;this.height=a.height;this.margins=a.margins;this.paddings=a.paddings}if(this.compatVersion()<=1)a.plot2=this._allowV1SecondAxis&&!!a.secondAxis;this._processOptionsCore(a);this._processExtensionPoints(); -return a},_processOptionsCore:function(a){if(this.parent){this._ibits=this.parent._ibits;this._tooltipOptions=this.parent._tooltipOptions}else{var b=u.renderer()!=="batik";if(b){b=a.interactive;if(b==null)b=true}if(b){var c=i.visual.Interactive;b=c.Interactive|c.ShowsInteraction;if(this._processTooltipOptions(a))b|=c.ShowsTooltip;if(a.animate&&$.support.svg)b|=c.Animatable;if(a.selectable){b|=c.Selectable;switch(i.parseSelectionMode(a.selectionMode)){case "rubberband":b|=c.SelectableByRubberband| -c.SelectableByClick;break;case "focuswindow":b|=c.SelectableByFocusWindow;break}}if(i.parseClearSelectionMode(a.clearSelectionMode)==="emptyspaceclick")b|=c.Unselectable;if(a.hoverable)b|=c.Hoverable;if(a.clickable)b|=c.Clickable|c.DoubleClickable}else b=0;this._ibits=b}},_tooltipDefaults:{gravity:"s",delayIn:200,delayOut:80,offset:2,opacity:0.9,html:true,fade:true,useCorners:false,arrowVisible:true,followMouse:false,format:undefined},_processTooltipOptions:function(a){var b=this.compatVersion()<= -1,c=a.tooltip,d=a.tooltipEnabled;if(d==null){if(c)d=c.enabled;if(d==null){if(b)d=a.showTooltips;if(d==null)d=true}}if(d){c||(c={});b&&this._importV1TooltipOptions(c,a);f.eachOwn(this._tooltipDefaults,function(e,g){var h=a["tooltip"+f.firstUpperCase(g)];if(h!==undefined)c[g]=h;else if(c[g]===undefined)c[g]=e})}else c={};this._tooltipOptions=c;return d},_importV1TooltipOptions:function(a,b){if(b=b.tipsySettings){this.extend(b,"tooltip");for(var c in b)if(a[c]===undefined)a[c]=b[c];if(a.html==null)a.html= -false}},render:function(a,b,c){var d;i.debug>1&&i.group("CCC RENDER");this._suspendSelectionUpdate();try{this.useTextMeasureCache(function(){try{if(!this.isPreRendered||b)this._preRender({reloadData:c});else!this.parent&&this.isPreRendered&&i.removeTipsyLegends();this.basePanel.render({bypassAnimation:a,recreate:b})}catch(e){if(e instanceof NoDataException){i.debug>1&&this._log("No data found.");this._addErrorPanelMessage("No data found",true)}else{d=true;i.logError(e.message);i.debug>0&&this._addErrorPanelMessage("Error: "+ -e.message,false)}}})}finally{d||this._resumeSelectionUpdate();i.debug>1&&i.groupEnd()}return this},_addErrorPanelMessage:function(a,b){var c=this.options;c=(new u.Panel).canvas(c.canvas).width(this.width).height(this.height);a=c.anchor("center").add(u.Label).text(a);b&&this.extend(a,"noDataMessage");c.render()},useTextMeasureCache:function(a,b){var c=this.root;c=c._textMeasureCache||(c._textMeasureCache=u.Text.createCache());return u.Text.usingCache(c,a,b||this)},animate:function(a,b){return this.basePanel.animate(a, -b)},animatingStart:function(){return this.basePanel.animatingStart()},animatable:function(){return this._animatable&&this.base()},isOrientationVertical:function(a){return(a||this.options.orientation)===i.orientation.vertical},isOrientationHorizontal:function(a){return(a||this.options.orientation)===i.orientation.horizontal},dispose:function(){if(!this._disposed)this._disposed=true},defaults:{width:400,height:300,orientation:"vertical",ignoreNulls:true,crosstabMode:true,isMultiValued:false,seriesInRows:false, -groupedLabelSep:undefined,animate:true,titlePosition:"top",titleAlign:"center",legend:false,legendPosition:"bottom",v1StyleTooltipFormat:function(a,b,c,d){return a+", "+b+": "+this.chart.options.valueFormat(c)+(d&&d.percent?" ("+d.percent.label+")":"")},valueFormat:f.scope(function(){var a=u.Format.number().fractionDigits(0,2);return function(b){return a.format(b)}}),percentValueFormat:f.scope(function(){var a=u.Format.number().fractionDigits(0,1);return function(b){return a.format(b*100)+"%"}}), -clickable:false,doubleClickMaxDelay:300,hoverable:false,selectable:false,selectionMode:"rubberband",ctrlSelectMode:true,clearSelectionMode:"emptySpaceClick",compatVersion:Infinity}});i.BaseChart.add({visualRoles:null,visualRoleList:null,_serRole:null,_dataPartRole:null,_measureVisualRoles:null,visualRole:function(a){var b=f.getOwn(this.visualRoles,a);if(!b)throw f.error.operationInvalid("roleName","There is no visual role with name '{0}'.",[a]);return b},measureVisualRoles:function(){return this._measureVisualRoles}, -measureDimensionsNames:function(){return f.query(this._measureVisualRoles).select(function(a){return a.firstDimensionName()}).where(f.notNully).array()},_constructVisualRoles:function(){var a=this.parent;if(a){this.visualRoles=a.visualRoles;this.visualRoleList=a.visualRoleList;this._measureVisualRoles=a._measureVisualRoles;["_multiChartRole","_serRole","_colorRole","_dataPartRole"].forEach(function(b){var c=a[b];if(c)this[b]=c},this)}else{this.visualRoles={};this.visualRoleList=[];this._measureVisualRoles= -[]}},_hasDataPartRole:f.fun.constant(false),_getSeriesRoleSpec:f.fun.constant(null),_getColorRoleSpec:f.fun.constant(null),_addVisualRole:function(a,b){b=f.set(b,"index",this.visualRoleList.length);b=new i.visual.Role(a,b);this.visualRoleList.push(b);this.visualRoles[a]=b;b.isMeasure&&this._measureVisualRoles.push(b);return b},_initVisualRoles:function(){this._multiChartRole=this._addVisualRole("multiChart",{defaultDimension:"multiChart*",requireIsDiscrete:true});if(this._hasDataPartRole())this._dataPartRole= -this._addVisualRole("dataPart",{defaultDimension:"dataPart",requireSingleDimension:true,requireIsDiscrete:true,dimensionDefaults:{isHidden:true,comparer:f.compare}});var a=this._getSeriesRoleSpec();if(a)this._serRole=this._addVisualRole("series",a);if(a=this._getColorRoleSpec())this._colorRole=this._addVisualRole("color",a)},_assertUnboundRoleIsOptional:function(a){if(a.isRequired)throw f.error.operationInvalid("Chart type requires unassigned role '{0}'.",[a.name]);},_bindVisualRolesPreI:function(){f.eachOwn(this.visualRoles, -function(g){g.setIsReversed(false)});var a=[],b=this.options,c=b.visualRoles;this.visualRoleList.forEach(function(g){g=g.name;var h=b[g+"Role"];if(h!==undefined){if(!c)c=b.visualRoles={};if(c[g]===undefined)c[g]=h}});var d;if(c){d={};var e=f.query(f.keys(c)).select(this.visualRole,this).array();e.sort(function(g,h){return g.index-h.index});e.forEach(function(g){var h=g.name,j=c[h],l,m;if(f.object.is(j)){f.nullyTo(j.isReversed,false)&&g.setIsReversed(true);if((m=j.from)&&m!==h){h=this.visualRoles[m]|| -f.fail.operationInvalid("Source role '{0}' is not supported by the chart type.",[m]);g.setSourceRole(h);a.push(g)}else l=j.dimensions}else l=j;if(l!==undefined){l||this._assertUnboundRoleIsOptional(g);l=i.data.GroupingSpec.parse(l);g.preBind(l);l.dimensions().each(function(k){if(f.hasOwn(d,k.name))delete d[k.name];else d[k.name]=g})}},this)}this._sourcedRoles=a;this._dimsBoundToSingleRole=d},_bindVisualRolesPreII:function(){var a=this._dimsBoundToSingleRole;if(a){delete this._dimsBoundToSingleRole; -f.eachOwn(a,this._setRoleBoundDimensionDefaults,this)}var b=this._sourcedRoles;delete this._sourcedRoles;f.query(this.visualRoleList).where(function(c){return c.defaultSourceRoleName&&!c.sourceRole&&!c.isPreBound()}).each(function(c){var d=this.visualRoles[c.defaultSourceRoleName];if(d){c.setSourceRole(d,true);b.push(c)}},this);b.forEach(function(c){var d=c.sourceRole;d.isReversed&&c.setIsReversed(!c.isReversed);!c.defaultDimensionName&&d.isPreBound()&&c.preBind(d.preBoundGrouping())})},_setRoleBoundDimensionDefaults:function(a, -b){this._complexTypeProj.setDimDefaults(b,a.dimensionDefaults)},_bindVisualRolesPostI:function(){function a(p,q){f.array.lazy(n,p).push(q)}function b(p){return k.hasDim(p)}function c(p,q){f.array.is(q)?q.forEach(function(s){a(s,p)}):a(q,p);p.setSourceRole(null);p.preBind(i.data.GroupingSpec.parse(q))}function d(p,q){if(q.length)p.requireSingleDimension?c(p,q[0]):c(p,q)}function e(p,q){k.setDim(q,{isHidden:true});c(p,q)}function g(p){m._assertUnboundRoleIsOptional(p);p.bind(null);p.setSourceRole(null)} -function h(p){p.preBoundGrouping().dimensionNames().forEach(a)}function j(p){if(p.sourceRole&&!p.isDefaultSourceRole)o.push(p);else{var q=p.defaultDimensionName;if(q){var s=q.match(/^(.*?)(\*)?$/)||f.fail.argumentInvalid("defaultDimensionName");q=s[1];if(s[2]){if(s=k.groupDimensionsNames(q)){d(p,s);return}}else if(b(q)){c(p,q);return}if(p.autoCreateDimension)e(p,q);else p.sourceRole?o.push(p):g(p)}else p.sourceRole?o.push(p):g(p)}}function l(p){var q=p.sourceRole;q.isPreBound()?p.preBind(q.preBoundGrouping()): -g(p)}var m=this,k=m._complexTypeProj,n={},o=[];f.query(m.visualRoleList).where(function(p){return p.isPreBound()}).each(h);f.query(m.visualRoleList).where(function(p){return!p.isPreBound()}).each(j);o.forEach(l);f.query(f.ownKeys(n)).where(function(p){return n[p].length===1}).each(function(p){m._setRoleBoundDimensionDefaults(n[p][0],p)})},_bindVisualRolesPostII:function(a){f.query(this.visualRoleList).where(function(b){return b.isPreBound()}).each(function(b){b.postBind(a)})},_logVisualRoles:function(){var a= -f.ownKeys(this.visualRoles),b=Math.max(10,f.query(a).select(function(d){return d.length}).max());a=f.string.padRight("VisualRole",b)+" < Dimension(s)";var c=["VISUAL ROLES MAP SUMMARY",i.logSeparator,a,f.string.padRight("",b+1,"-")+"+--------------"];f.eachOwn(this.visualRoles,function(d,e){c.push(f.string.padRight(e,b)+" | "+(d.grouping||"-"))});c.push("");this._log(c.join("\n"))},_getDataPartDimName:function(){var a=this._dataPartRole;if(a){if(a.isBound())return a.firstDimensionName();var b=a.preBoundGrouping(); -if(b)return b.firstDimensionName();return a.defaultDimensionName}}});i.BaseChart.add({dataEngine:null,data:null,_partData:null,_visibleDataCache:null,resultset:[],metadata:[],_constructData:function(a){if(this.parent)this.dataEngine=this.data=a.data||f.fail.argumentRequired("options.data")},_checkNoDataI:function(){if(!this.parent&&!this.allowNoData&&this.resultset.length===0)throw new NoDataException;},_checkNoDataII:function(){if(!this.parent&&!this.allowNoData&&(!this.data||!this.data.count())){this.data= -null;throw new NoDataException;}},_initData:function(a){if(!this.parent){var b=this.data;if(b)if(f.get(a,"reloadData",true))this._onReloadData();else{b.clearVirtuals();b.disposeChildren()}else this._onLoadData()}delete this._partData;delete this._visibleDataCache;i.debug>=3&&this._log(this.data.getInfo())},_onLoadData:function(){var a=this.data,b=this._translation;!a&&!b||f.assert("Invalid state.");a=this.options;var c=this._getDataPartDimName(),d=this._complexTypeProj||f.assert("Invalid state."), -e=this._createTranslationOptions(c);b=this._translation=this._createTranslation(e);if(i.debug>=3){this._log(b.logSource());this._log(b.logTranslatorType())}b.configureType();c&&!d.isReadOrCalc(c)&&this._addDefaultDataPartCalculation(c);i.debug>=3&&this._log(b.logVItem());this._bindVisualRolesPostI();c=new i.data.ComplexType;d.configureComplexType(c,e);this._bindVisualRolesPostII(c);i.debug>=10&&this._log(c.describe());i.debug>=3&&this._logVisualRoles();a=this.dataEngine=this.data=new i.data.Data({type:c, -labelSep:a.groupedLabelSep,keySep:e.separator});d={where:this._getLoadFilter(),isNull:this._getIsNullDatum()};b=b.execute(a);a.load(b,d)},_onReloadData:function(){var a=this.data,b=this._translation;a&&b||f.assert("Invalid state.");b.setSource(this.resultset);i.debug>=3&&this._log(b.logSource());var c={where:this._getLoadFilter(),isNull:this._getIsNullDatum()};b=b.execute(a);a.load(b,c)},_createComplexTypeProject:function(){var a=this.options,b=new i.data.ComplexTypeProject(a.dimensionGroups),c=a.dimensions; -for(var d in c)b.setDim(d,c[d]);if(c=this._getDataPartDimName()){b.setDim(c);this._addPlot2SeriesDataPartCalculation(b,c)}(a=a.calculations)&&a.forEach(function(e){b.setCalc(e)});return b},_getLoadFilter:function(){if(this.options.ignoreNulls){var a=this;return function(b){(b=b.isNull)&&i.debug>=4&&a._info("Datum excluded.");return!b}}},_getIsNullDatum:function(){var a=this.measureDimensionsNames(),b=a.length;if(b)return function(c){c=c.atoms;for(var d=0;d1)return this._partData.where([f.set({},b,a)]);a=a[0]}var c=this._partData._childrenByKey[a+ -""];if(!c){c={v:a};if(a==="trend")if(a=this._firstTrendAtomProto)c.f=a.f;c=new i.data.Data({parent:this._partData,atoms:f.set({},b,c),dimNames:[b],datums:[]})}return c},visibleData:function(a,b){var c=f.get(b,"ignoreNulls",true),d=f.get(b,"inverted",false);if(c&&this.options.ignoreNulls)c=false;var e=f.lazy(this,"_visibleDataCache");d=d+"|"+c+"|"+a;var g=e[d];if(!g){b=b?Object.create(b):{};b.ignoreNulls=c;g=e[d]=this._createVisibleData(a,b)}return g},_createVisibleData:function(a,b){a=this.partData(a); -if(!a)return null;b=f.get(b,"ignoreNulls");var c=this._serRole;return c&&c.grouping?c.flatten(a,{visible:true,isNull:b?false:null}):a},_generateTrends:function(){this._dataPartRole&&f.query(f.own(this.axes)).selectMany(f.propGet("dataCells")).where(f.propGet("trend")).distinct(function(a){return a.role.name+"|"+(a.dataPartValue||"")}).each(this._generateTrendsDataCell,this)},_interpolate:function(){f.query(f.own(this.axes)).selectMany(f.propGet("dataCells")).where(function(a){a=a.nullInterpolationMode; -return!!a&&a!=="none"}).distinct(function(a){return a.role.name+"|"+(a.dataPartValue||"")}).each(this._interpolateDataCell,this)},_interpolateDataCell:function(){},_generateTrendsDataCell:function(){},setData:function(a,b){this.setResultset(a.resultset);this.setMetadata(a.metadata);$.extend(this.options,b);return this},setResultset:function(a){!this.parent||f.fail.operationInvalid("Can only set resultset on root chart.");this.resultset=a;a.length||this._log("Warning: Resultset is empty");return this}, -setMetadata:function(a){!this.parent||f.fail.operationInvalid("Can only set resultset on root chart.");this.metadata=a;a.length||this._log("Warning: Metadata is empty");return this}});i.BaseChart.add({_initPlots:function(a){this.plotPanelList=null;if(this.parent){a=this.root;this.plots=a.plots;this.plotList=a.plotList;this.plotsByType=a.plotsByType}else{this.plots={};this.plotList=[];this.plotsByType={};this._initPlotsCore(a)}},_initPlotsCore:function(){},_addPlot:function(a){var b=this.plotsByType, -c=this.plots,d=a.type,e=a.index,g=a.name,h=a.id;if(g&&f.hasOwn(c,g))throw f.error.operationInvalid("Plot name '{0}' already taken.",[g]);if(f.hasOwn(c,h))throw f.error.operationInvalid("Plot id '{0}' already taken.",[h]);b=f.array.lazy(b,d);if(f.hasOwn(b,e))throw f.error.operationInvalid("Plot index '{0}' of type '{1}' already taken.",[e,d]);a.globalIndex=this.plotList.length;b[e]=a;this.plotList.push(a);c[h]=a;if(g)c[g]=a},_collectPlotAxesDataCells:function(a,b){var c=[];a.collectDataCells(c);c.length&& -f.query(c).where(function(d){return d.isBound()}).each(function(d){var e=f.array.lazy(b,d.axisType);f.array.lazy(e,d.axisIndex).push(d)})},_addPlotPanel:function(a){f.lazy(this,"plotPanels")[a.plot.id]=a;f.array.lazy(this,"plotPanelList").push(a)},_createPlotPanels:function(){throw f.error.notImplemented();}});i.BaseChart.add({colors:null,axes:null,axesList:null,axesByType:null,_axisClassByType:{color:i.visual.ColorAxis,size:i.visual.SizeAxis,base:da,ortho:da},_axisCreateWhere:{color:1,size:2,base:3, -ortho:3},_axisCreationOrder:["color","size","base","ortho"],_axisCreateIfUnbound:{},_initAxes:function(a){this.axes={};this.axesList=[];this.axesByType={};delete this._rolesColorScale;var b;if(this.parent)b=this.root._dataCellsByAxisTypeThenIndex;else{b={};this.plotList.forEach(function(d){this._collectPlotAxesDataCells(d,b)},this);this._fixTrendsLabel(b)}this._dataCellsByAxisTypeThenIndex=b;var c=0;this.parent||(c|=1);if(this.parent||!a)c|=2;this._axisCreateHere=c;this._axisCreationOrder.forEach(function(d){if((this._axisCreateWhere[d]& -c)!==0){var e,g=b[d];if(g)(e=this._axisClassByType[d])&&g.forEach(function(h,j){new e(this,d,j)},this);else if(this._axisCreateIfUnbound[d])(e=this._axisClassByType[d])&&new e(this,d,0)}},this);this.parent&&this.root.axesList.forEach(function(d){f.hasOwn(this.axes,d.id)||this._addAxis(d)},this)},_fixTrendsLabel:function(a){if(this._getDataPartDimName()){var b=f.query(f.ownKeys(a)).selectMany(function(d){return a[d]}).selectMany().first(function(d){return!!d.trend});if(b){var c=i.trends.get(b.trend.type).dataPartAtom; -b=b.trend.label;if(b===undefined)b=c.f;this._firstTrendAtomProto={v:c.v,f:b}}else delete this._firstTrendAtomProto}},_addAxis:function(a){this.axes[a.id]=a;if(a.chart===this)a.axisIndex=this.axesList.length;this.axesList.push(a);var b=f.array.lazy(this.axesByType,a.type),c=b.count||0;a.typeIndex=c;b[a.index]=a;if(!c)b.first=a;b.count=c+1;a.type==="color"&&a.isBound()&&this._onColorAxisScaleSet(a);return this},_getAxis:function(a,b){if((a=this.axesByType[a])&&b!=null&&+b>=0)return a[b]},_bindAxes:function(){var a= -this._axisCreateHere;f.eachOwn(this._dataCellsByAxisTypeThenIndex,function(b,c){this._axisCreateWhere[c]&a&&b.forEach(function(d,e){e=this.axes[i.buildIndexedId(c,e)];e.isBound()||e.bind(d)},this)},this)},_setAxesScales:function(){if(!this.parent){var a=this.axesByType.color;a&&a.forEach(function(b){if(b.isBound()){this._createColorAxisScale(b);this._onColorAxisScaleSet(b)}},this)}},_createAxisScale:function(a){var b=this._createScaleByAxis(a);b.isNull&&i.debug>=3&&this._log(f.format("{0} scale for axis '{1}'- no data", -[a.scaleType,a.id]));return a.setScale(b).scale},_createScaleByAxis:function(a){return this["_create"+f.firstUpperCase(a.scaleType)+"ScaleByAxis"].call(this,a)},_createDiscreteScaleByAxis:function(a){var b=this.visibleData(a.dataCells.map(function(c){return c.dataPartValue}),{ignoreNulls:false});b=b&&a.role.flatten(b);a=new u.Scale.ordinal;if(!b||!b.count())a.isNull=true;else{b=b.children().select(function(c){return f.nullyTo(c.value,"")}).array();a.domain(b)}return a},_createTimeSeriesScaleByAxis:function(a){a= -this._getContinuousVisibleExtent(a);var b=new u.Scale.linear;if(a){var c=a.min,d=a.max;if(d-c===0)d=new Date(d.getTime()+36E5);b.domain(c,d);b.minLocked=a.minLocked;b.maxLocked=a.maxLocked}else b.isNull=true;return b},_createNumericScaleByAxis:function(a){var b=this._getContinuousVisibleExtentConstrained(a),c=new u.Scale.linear;if(b){var d=b.min,e=b.max,g=function(){var h=e-d;if(h&&Math.abs(h)<=1.0E-10){d=(d+e)/2;d=e=+d.toFixed(10);h=0}if(h){if(h<0)if(!b.maxLocked||b.minLocked)e=Math.abs(d)>1.0E-10? -d*1.01:+0.1;else d=Math.abs(e)>1.0E-10?e*0.99:-0.1}else{b.minLocked||(d=Math.abs(d)>1.0E-10?d*0.99:-0.1);if(!b.maxLocked||b.minLocked)e=Math.abs(e)>1.0E-10?e*1.01:+0.1}};g();if(a.option("OriginIsZero"))if(d===0)b.minLocked=true;else if(e===0)b.maxLocked=true;else if(d*e>0)if(d>0){if(!b.minLocked){b.minLocked=true;d=0}}else if(!b.maxLocked){b.maxLocked=true;e=0}g();c.domain(d,e);c.minLocked=b.minLocked;c.maxLocked=b.maxLocked}else c.isNull=true;return c},_warnSingleContinuousValueRole:function(a){a.grouping.isSingleDimension|| -this._warn("A linear scale can only be obtained for a single dimension role.");a.grouping.isDiscrete()&&this._warn(f.format("The single dimension of role '{0}' should be continuous.",[a.name]))},_getContinuousVisibleExtentConstrained:function(a,b,c){var d=false,e=false;if(b==null){b=a.option("FixedMin");d=b!=null}if(c==null){c=a.option("FixedMax");e=c!=null}if(b==null||c==null){a=this._getContinuousVisibleExtent(a);if(!a)return null;if(b==null)b=a.min;if(c==null)c=a.max}return{min:b,max:c,minLocked:d, -maxLocked:e}},_getContinuousVisibleExtent:function(a){var b=a.dataCells;if(b.length===1)return this._getContinuousVisibleCellExtent(a,b[0]);return f.query(b).select(function(c){return this._getContinuousVisibleCellExtent(a,c)},this).reduce(i.unionExtents,null)},_getContinuousVisibleCellExtent:function(a,b){var c=b.role;this._warnSingleContinuousValueRole(c);if(c.name==="series")throw f.error.notImplemented();a=a.scaleUsesAbs();if(b=(b=this.visibleData(b.dataPartValue))&&b.dimensions(c.firstDimensionName()).extent({abs:a})){c= -b.min.value;b=b.max.value;return{min:a?Math.abs(c):c,max:a?Math.abs(b):b}}},_createColorAxisScale:function(a){var b;if(a.dataCells)b=a.scaleType==="discrete"?this._createDiscreteColorAxisScale(a):this._createContinuousColorAxisScale(a);return a.setScale.apply(a,b)},_createDiscreteColorAxisScale:function(a){var b=f.query(a.dataCells).selectMany(function(c){return c.domainItemValues()}).array();a.domainValues=b;return[a.scheme()(b),true]},_createContinuousColorAxisScale:function(a){if(a.dataCells.length=== -1){this._warnSingleContinuousValueRole(a.role);var b=this.root.visibleData(a.dataCell.dataPartValue),c=a.option("NormByCategory");b={type:a.option("ScaleType"),colors:a.option("Colors")().range(),colorDomain:a.option("Domain"),colorMin:a.option("Min"),colorMax:a.option("Max"),colorMissing:a.option("Missing"),data:b,colorDimension:a.role.firstDimensionName(),normPerBaseCategory:c};if(!c)return[ya(b)];a.scalesByCateg=xa(b)}return[]},_onColorAxisScaleSet:function(a){switch(a.index){case 0:this.colors= -a.scheme();break;case 1:if(this._allowV1SecondAxis)this.secondAxisColor=a.scheme();break}},_getRoleColorScale:function(a){return f.lazy(f.lazy(this,"_rolesColorScale"),a,this._createRoleColorScale,this)},_createRoleColorScale:function(a){function b(g){var h=""+g;f.hasOwnProp.call(e,h)||(e[h]=d(g))}var c,d,e={};this.axesByType.color.forEach(function(g){var h=g.role;if((h.name===a||h.sourceRole&&h.sourceRole.name===a)&&g.scale&&(g.index===0||g.option.isSpecified("Colors")||g.option.isSpecified("Map"))){d= -g.scale;c||(c=d);g.domainValues.forEach(b)}},this);if(!c)return i.createColorScheme()();d=function(g){var h=""+g;if(f.hasOwnProp.call(e,h))return e[h];g=c(g);return e[h]=g};f.copy(d,c);return d},_onLaidOut:function(){}});i.BaseChart.add({basePanel:null,titlePanel:null,legendPanel:null,_multiChartPanel:null,_initChartPanels:function(a){this._initBasePanel();this._initTitlePanel();var b=a&&!this.parent,c=this._initLegendPanel();b&&this._initMultiChartPanel();c&&this._initLegendScenes(c);if(!b){b=this.options; -this._preRenderContent({margins:a?b.smallContentMargins:b.contentMargins,paddings:a?b.smallContentPaddings:b.contentPaddings,clickAction:b.clickAction,doubleClickAction:b.doubleClickAction})}},_preRenderContent:function(){},_initBasePanel:function(){var a=this.parent;this.basePanel=new i.BasePanel(this,a&&a._multiChartPanel,{margins:this.margins,paddings:this.paddings,size:{width:this.width,height:this.height}})},_initTitlePanel:function(){var a=this,b=a.options,c=b.title;if(!f.empty(c))this.titlePanel= -new i.TitlePanel(a,a.basePanel,{title:c,font:b.titleFont,anchor:b.titlePosition,align:b.titleAlign,alignTo:b.titleAlignTo,offset:b.titleOffset,keepInBounds:b.titleKeepInBounds,margins:b.titleMargins,paddings:b.titlePaddings,titleSize:b.titleSize,titleSizeMax:b.titleSizeMax})},_initLegendPanel:function(){var a=this.options;if(a.legend){var b=new i.visual.Legend(this,"legend",0);return this.legendPanel=new i.LegendPanel(this,this.basePanel,{anchor:b.option("Position"),align:b.option("Align"),alignTo:a.legendAlignTo, -offset:a.legendOffset,keepInBounds:a.legendKeepInBounds,size:b.option("Size"),sizeMax:b.option("SizeMax"),margins:b.option("Margins"),paddings:b.option("Paddings"),font:b.option("Font"),scenes:f.getPath(a,"legend.scenes"),textMargin:a.legendTextMargin,itemPadding:a.legendItemPadding,markerSize:a.legendMarkerSize})}},_getLegendBulletRootScene:function(){return this.legendPanel&&this.legendPanel._getBulletRootScene()},_initMultiChartPanel:function(){var a=this.basePanel,b=this.options;this._multiChartPanel= -new i.MultiChartPanel(this,a,{margins:b.contentMargins,paddings:b.contentPaddings});this._multiChartPanel.createSmallCharts();a._children.unshift(a._children.pop())},_coordinateSmallChartsLayout:function(){},_initLegendScenes:function(a){function b(h,j){var l=j.option("LegendClickMode")==="togglevisible",m=h.domainData();d||(d=a._getBulletRootScene());var k;if(l)if((l=m.atoms[g])&&l.value==="trend")k="none";var n=d.createGroup({source:m,colorAxis:j,clickMode:k,extensionPrefix:i.buildIndexedId("", -e++)});h.legendBulletGroupScene=n;h.domainItemDatas().each(function(o){var p=n.createItem({source:o});o=h.domainItemDataValue(o);p.color=j.scale(o)})}var c=this.axesByType.color;if(c){var d,e=0,g=this._getDataPartDimName();f.query(c).where(function(h){return h.option("LegendVisible")}).each(function(h){h.dataCells&&h.dataCells.forEach(function(j){j.role.isDiscrete()&&b(j,h)})})}}});i.BaseChart.add({_updateSelectionSuspendCount:0,_lastSelectedDatums:null,clearSelections:function(){this.data.owner.clearSelected()&& -this.updateSelections();return this},_updatingSelections:function(a,b){this._suspendSelectionUpdate();try{a.call(b||this)}finally{this._resumeSelectionUpdate()}},_suspendSelectionUpdate:function(){if(this===this.root)this._updateSelectionSuspendCount++;else this.root._suspendSelectionUpdate()},_resumeSelectionUpdate:function(){if(this===this.root){if(this._updateSelectionSuspendCount>0)--this._updateSelectionSuspendCount||this.updateSelections()}else this.root._resumeSelectionUpdate()},updateSelections:function(a){if(this=== -this.root){if(this._inUpdateSelections||this._updateSelectionSuspendCount)return this;var b=this._calcSelectedChangedDatums();if(!b)return this;i.removeTipsyLegends();this._inUpdateSelections=true;try{var c=this.options.selectionChangedAction;if(c){var d=this.data.selectedDatums(),e=b.values();c.call(this.basePanel.context(),d,e)}f.get(a,"render",true)&&this.useTextMeasureCache(function(){this.basePanel.renderInteractive()},this)}finally{this._inUpdateSelections=false}}else this.root.updateSelections(); -return this},_calcSelectedChangedDatums:function(){if(this.data){var a,b=this.data.selectedDatumMap();if(a=this._lastSelectedDatums){a=a.symmetricDifference(b);if(!a.count)return}else{if(!b.count)return;a=b.clone()}this._lastSelectedDatums=b;return a}},_onUserSelection:function(a){if(!a||!a.length)return a;if(this===this.root){var b=this.options.userSelectionAction;return b?b.call(this.basePanel.context(),a)||a:a}return this.root._onUserSelection(a)}});i.BaseChart.add({_processExtensionPoints:function(){var a; -if(this.parent)a=this.parent._components;else{var b=this.options.extensionPoints;a={};if(b)for(var c in b){var d,e;e=c.indexOf("_");if(e>0){d=c.substring(0,e);e=c.substr(e+1);if(d&&e)(f.getOwn(a,d)||(a[d]=new f.OrderedMap)).add(e,b[c])}}}this._components=a},extend:function(a,b,c){f.array.is(b)?b.forEach(function(d){this._extendCore(a,d,c)},this):this._extendCore(a,b,c)},_extendCore:function(a,b,c){if(a){var d=f.getOwn(this._components,b);if(d){if(a.borderPanel)a=a.borderPanel;var e=i.debug>=3?[]: -null,g=f.get(c,"constOnly",false),h=a.wrap,j={tag:i.extensionTag},l=a instanceof O;d.forEach(function(m,k){if(a.isLocked&&a.isLocked(k))e&&e.push(k+": locked extension point!");else if(a.isIntercepted&&a.isIntercepted(k))e&&e.push(k+":"+i.stringify(m)+" (controlled)");else{e&&e.push(k+": "+i.stringify(m));if(m!=null){var n=typeof m;if(n==="object"){if(k==="svg"||k==="css")if(n=a.propertyValue(k))m=f.copy(n,m)}else if(l&&(h||g)&&n==="function"){if(g)return;if(k!=="add")m=h.call(a,m,k)}}if(typeof a[k]=== -"function")k!="add"&&a.intercept&&a.properties[k]?a.intercept(k,m,j):a[k](m);else a[k]=m}});if(e)if(e.length)this._log("Applying Extension Points for: '"+b+"'\n\t* "+e.join("\n\t* "));else i.debug>=5&&this._log("No Extension Points for: '"+b+"'")}}else i.debug>=4&&this._log("Applying Extension Points for: '"+b+"' (target mark does not exist)")},_getExtension:function(a,b){var c;if(f.array.is(a))for(var d=a.length-1,e;d>=0;){if((c=f.getOwn(this._components,a[d--]))&&(e=c.get(b))!==undefined)return e}else if(c= -f.getOwn(this._components,a))return c.get(b)},_getComponentExtensions:function(a){return f.getOwn(this._components,a)},_getConstantExtension:function(a,b){a=this._getExtension(a,b);if(!f.fun.is(a))return a}});f.type("pvc.BasePanel",i.Abstract).add(i.visual.Interactive).init(function(a,b,c){this.chart=a;this.base();this.axes={};if(c){if(c.scenes){this._sceneTypeExtensions=c.scenes;delete c.scenes}var d=c.axes;if(d){f.copy(this.axes,d);delete c.axes}}$.extend(this,c);if(!this.axes.color)this.axes.color= -a.axes.color;this.position={};d=c&&c.margins;if(!b&&d===undefined)d=3;this.margins=new F(d);this.paddings=new F(c&&c.paddings);this.size=new M(c&&c.size);this.sizeMax=new M(c&&c.sizeMax);if(b){this.parent=b;this.isTopRoot=false;this.root=(this.isRoot=b.chart!==a)?this:b.root;this.topRoot=b.topRoot;this._ibits=b._ibits;if(this.isRoot){this.position.left=a.left;this.position.top=a.top}b._addChild(this)}else{this.parent=null;this.root=this;this.topRoot=this;this.isTopRoot=this.isRoot=true;this._ibits= -a._ibits}this.data=(this.isRoot?a:b).data;if(this.isRoot)this.offset=this.alignTo=this.align=this.anchor=null;else{this.align=i.parseAlign(this.anchor,this.align);b=this.alignTo;c=this.anchor;if(b!=null&&b!==""&&(c==="left"||c==="right")){if(b!=="page-middle")b=isNaN(+b.charAt(0))?i.parseAlign(c,b):L.parse(b)}else b=this.align;this.alignTo=b;this.offset=new X(this.offset)}if(this.borderWidth==null){var e;if(b=this._getExtensionId())if(this._getExtension(b,"strokeStyle")!=null){e=+this._getConstantExtension(b, -"lineWidth");if(isNaN(e)||!isFinite(e))e=null}this.borderWidth=e==null?0:1.5}e=i.visual.Interactive;b=this._ibits;b=f.bit.set(b,e.Clickable,a._ibits&e.Clickable&&!!this.clickAction);this._ibits=b=f.bit.set(b,e.DoubleClickable,a._ibits&e.DoubleClickable&&!!this.doubleClickAction)}).add({chart:null,parent:null,_children:null,type:u.Panel,_extensionPrefix:"",_rubberSelectableMarks:null,height:null,width:null,borderWidth:null,anchor:"top",pvPanel:null,margins:null,paddings:null,isRoot:false,isTopRoot:false, -root:null,topRoot:null,_layoutInfo:null,_signs:null,data:null,dataPartValue:null,_animating:0,_selectingByRubberband:false,_v1DimRoleName:{series:"series",category:"category",value:"value"},_sceneTypeExtensions:null,clickAction:null,doubleClickAction:null,compatVersion:function(a){return this.chart.compatVersion(a)},_createLogInstanceId:function(){return""+this.constructor+this.chart._createLogChildSuffix()},defaultVisibleBulletGroupScene:function(){var a=this.axes.color;if(a&&a.option("LegendVisible")){var b= -this.dataPartValue;return f.query(a.dataCells).where(function(c){return c.dataPartValue===b}).select(function(c){return c.legendBulletGroupScene}).first(f.truthy)}return null},_getLegendBulletRootScene:function(){return this.chart._getLegendBulletRootScene()},_addChild:function(a){a.parent===this||f.assert("Child has a != parent.");(this._children||(this._children=[])).push(a)},_addSign:function(a){f.array.lazy(this,"_signs").push(a);a.selectableByRubberband()&&f.array.lazy(this,"_rubberSelectableMarks").push(a.pvMark)}, -visibleData:function(a){return this.chart.visibleData(this.dataPartValue,a)},partData:function(){return this.chart.partData(this.dataPartValue)},layout:function(a,b){if(!this._layoutInfo||f.get(b,"force",false)){var c=f.get(b,"referenceSize");if(!c&&a)c=f.copyOwn(a);var d=this.size.resolve(c),e=this.sizeMax.resolve(c);if(!a){if(d.width==null||d.height==null)throw f.error.operationInvalid("Panel layout without width or height set.");a=f.copyOwn(d)}if(!c&&a)c=f.copyOwn(a);if(e.width!=null&&a.width> -e.width)a.width=e.width;if(e.height!=null&&a.height>e.height)a.height=e.height;e=this.borderWidth/2;var g=(f.get(b,"margins")||this.margins).resolve(c),h=(f.get(b,"paddings")||this.paddings).resolve(c),j=F.inflate(g,e),l=F.inflate(h,e),m=j.width+l.width,k=j.height+l.height;e=new M(Math.max(a.width-m,0),Math.max(a.height-k,0));var n=f.copyOwn(d);if(n.width!=null)n.width=Math.max(n.width-m,0);if(n.height!=null)n.height=Math.max(n.height-k,0);d=this._layoutInfo||null;b=f.get(b,"canChange",true);c=this._layoutInfo= -{canChange:b,referenceSize:c,realMargins:g,realPaddings:h,borderWidth:this.borderWidth,margins:j,paddings:l,desiredClientSize:n,clientSize:e,pageClientSize:d?d.pageClientSize:e.clone(),previous:d};if(d){delete d.previous;delete d.pageClientSize}if(g=this._calcLayout(c)){c.clientSize=g;a={width:g.width+m,height:g.height+k}}else{a=a;g=e}this.isVisible=g.width>0&&g.height>0;delete c.desiredClientSize;this.width=a.width;this.height=a.height;!b&&d&&delete c.previous;if(i.debug>=5){this._log("Size = "+ -i.stringify(a));this._log("Margins = "+i.stringify(c.margins));this._log("Paddings = "+i.stringify(c.paddings));this._log("ClientSize = "+i.stringify(c.clientSize))}this._onLaidOut()}},_onLaidOut:function(){this.isRoot&&this.chart._onLaidOut()},_calcLayout:function(a){function b(v,y,z){for(var w=0;v--;){if(y.call(z,v,w)===false)return true;w++}return false}function c(v,y){o&&m._group("LayoutCycle #"+(y+1)+" (remaining: "+v+")");try{v=v>0;k=new F(0);n=f.copyOwn(l);var z;y=0;for(var w=A.length;y< -w;){z=A[y];o&&m._group("SIDE Child #"+(y+1)+" at "+z.anchor);try{if(d.call(this,z,v))return true}finally{o&&m._groupEnd()}y++}y=0;for(w=t.length;y0;v.layout(new M(n),x);if(v.isVisible){if(z=g.call(this,v,y))return false;var K=v._layoutInfo.requestPaddings; -if(e(w,K)){w=K;if(B>0){w=new F(w);o&&this._log("Child requested paddings change: "+i.stringify(w));return true}i.debug>=2&&this._warn("Child requests paddings change but iterations limit has been reached.")}h.call(this,v);v.anchor!=="fill"&&j.call(this,v)}return false}finally{o&&m._groupEnd()}},this);return z}function e(v,y){if(!y)return false;return f.query(F.names).each(function(z){if(Math.abs((y&&y[z]||0)-(v&&v[z]||0))>=0.1)return false})}function g(v,y){var z=false,w=v.width-n.width;if(w>0){i.debug>= -3&&this._log("Child added width = "+w);if(y){z=true;n.width+=w;l.width+=w}else i.debug>=2&&this._warn("Child wanted more width, but layout iterations limit has been reached.")}v=v.height-n.height;if(v>0){i.debug>=3&&this._log("Child added height ="+v);if(y){z=true;n.height+=v;l.height+=v}else i.debug>=2&&this._warn("Child wanted more height, but layout iterations limit has been reached.")}return z}function h(v){var y=v.anchor,z=v.align,w=v.alignTo,B;if(y==="fill"){y="left";B=k.left+n.width/2-v.width/ -2;z=w="middle"}else B=k[y];var H,K;switch(z){case "top":case "bottom":case "left":case "right":H=z;K=0;break;case "center":case "middle":H=s[q[y]];K=-v[p[H]]/2;break}var S,J;switch(w){case "top":case "bottom":case "left":case "right":J=w;S=J!==H?n[p[H]]:0;break;case "center":case "middle":J=s[q[y]];S=n[p[H]]/2;break;case "page-center":case "page-middle":J=s[q[y]];z=p[H];S=Math.min(n[z],a.pageClientSize[z])/2;break}K=k[J]+S+K;if(J=v.offset.resolve(n)){B+=J[r[y]]||0;K+=J[r[H]]||0}if(v.keepInBounds){if(B< -0)B=0;if(K<0)K=0}v.setPosition(f.set({},y,B,H,K))}function j(v){var y=v.anchor,z=p[y];v=v[z];k[y]+=v;n[z]-=v}var l,m=this,k,n,o;if(m._children){var p=i.BasePanel.orthogonalLength,q=i.BasePanel.relativeAnchor,s=i.BasePanel.leftTopAnchor,r=X.namesSidesToOffset,t=[],A=[];m._children.forEach(function(v){var y=v.anchor;if(y)if(y==="fill")t.push(v);else{f.hasOwn(q,y)||f.fail.operationInvalid("Unknown anchor value '{0}'",[y]);A.push(v)}});o=i.debug>=5;l=f.copyOwn(a.clientSize);var x={force:true,referenceSize:l}; -o&&m._group("CCC DOCK LAYOUT clientSize = "+i.stringify(l));try{b(5,c,m)}finally{o&&m._groupEnd()}}return l},invalidateLayout:function(){this._layoutInfo=null;this._children&&this._children.forEach(function(a){a.invalidateLayout()})},_create:function(a){if(!this.pvPanel||a){this.pvPanel=null;delete this._signs;this.layout();if(this.isVisible){this.isRoot&&this._creating();var b=this._layoutInfo.margins;a=this._layoutInfo.paddings;if(this.isTopRoot){this.pvRootPanel=this.pvPanel=(new u.Panel).canvas(this.chart.options.canvas); -this.pvRootPanel.lock("data",[new i.visual.Scene(null,{panel:this})]);if(b.width>0||b.height>0){this.pvPanel.width(this.width).height(this.height);this.pvPanel=this.pvPanel.add(u.Panel)}}else this.pvPanel=this.parent.pvPanel.add(this.type);var c=this.pvPanel,d=this.width-b.width,e=this.height-b.height;c.width(d).height(e);if(i.debug>=15&&(b.width>0||b.height>0))(this.isTopRoot?this.pvRootPanel:this.parent.pvPanel).add(this.type).width(this.width).height(this.height).left(this.position.left!=null? -this.position.left:null).right(this.position.right!=null?this.position.right:null).top(this.position.top!=null?this.position.top:null).bottom(this.position.bottom!=null?this.position.bottom:null).strokeStyle("orange").lineWidth(1).strokeDasharray("- .");var g={};f.eachOwn(this.position,function(j,l){c[l](j+b[l]);g[this.anchorLength(l)]=true},this);if(!g.width){b.left>0&&c.left(b.left);b.right>0&&c.right(b.right)}if(!g.height){b.top>0&&c.top(b.top);b.bottom>0&&c.bottom(b.bottom)}if(a.width>0||a.height> -0)this.pvPanel=c.add(u.Panel).width(d-a.width).height(e-a.height).left(a.left).top(a.top);c.borderPanel=c;c.paddingPanel=this.pvPanel;this.pvPanel.paddingPanel=this.pvPanel;this.pvPanel.borderPanel=c;if(i.debug>=15){this.pvPanel.strokeStyle("lightgreen").lineWidth(1).strokeDasharray("- ");this.pvPanel!==c&&c.strokeStyle("blue").lineWidth(1).strokeDasharray(". ")}a=this._getExtensionId();new i.visual.Panel(this,null,{panel:c,extensionId:a});this._createCore(this._layoutInfo);this.isTopRoot&&this._initRubberBand(); -this.applyExtensions();if(this.isRoot&&i.debug>5){var h=["SCALES SUMMARY",i.logSeparator];this.chart.axesList.forEach(function(j){var l=j.scale;if(l){var m=l.domain&&l.domain();l=l.range&&l.range();h.push(j.id);h.push(" domain: "+(!m?"?":i.stringify(m)));h.push(" range : "+(!l?"?":i.stringify(l)))}},this);this._log(h.join("\n"))}}}},_creating:function(){this._children&&this._children.forEach(function(a){a._creating()})},_createCore:function(){this._children&&this._children.forEach(function(a){a._create()})}, -render:function(a){if(!this.isTopRoot)return this.topRoot.render(a);this._create(f.get(a,"recreate",false));if(this.isVisible){this._onRender();var b=this.pvRootPanel;this._animating=this.chart.animatable()&&!f.get(a,"bypassAnimation",false)?1:0;try{b.render();if(this._animating){this._animating=2;var c=this;b.transition().duration(2E3).ease("cubic-in-out").start(function(){c._animating=0;c._onRenderEnd(true)})}else this._onRenderEnd(false)}finally{this._animating=0}}},_onRender:function(){var a= -this.chart.options.renderCallback;if(a)if(this.compatVersion()<=1)a.call(this.chart);else{var b=this.context();a.call(b,b.scene)}},_onRenderEnd:function(a){this._children&&this._children.forEach(function(b){b._onRenderEnd(a)})},renderInteractive:function(){if(this.isVisible){var a=this._getSelectableMarks();if(a&&a.length)a.forEach(function(b){b.render()});else if(!this._children){this.pvPanel.render();return}this._children&&this._children.forEach(function(b){b.renderInteractive()})}},_getSelectableMarks:function(){return this._rubberSelectableMarks}, -animate:function(a,b){return this.topRoot._animating===1?a:b},animatingStart:function(){return this.topRoot._animating===1},animating:function(){return this.topRoot._animating>0},setPosition:function(a){for(var b in a)if(f.hasOwn(F.namesSet,b)){var c=a[b];if(c===null)delete this.position[b];else{c=+c;if(!isNaN(c)&&isFinite(c))this.position[b]=c}}},createAnchoredSize:function(a,b){if(this.isAnchorTopOrBottom())return new M(b.width,Math.min(b.height,a));return new M(Math.min(b.width,a),b.height)},applyExtensions:function(){this._signs&& -this._signs.forEach(function(a){a.applyExtensions()})},extend:function(a,b,c){this.chart.extend(a,this._makeExtensionAbsId(b),c)},extendAbs:function(a,b,c){this.chart.extend(a,b,c)},_extendSceneType:function(a,b,c){(a=f.get(this._sceneTypeExtensions,a))&&i.extendType(b,a,c)},_absBaseExtId:{abs:"base"},_absSmallBaseExtId:{abs:"smallBase"},_getExtensionId:function(){if(this.isRoot)return!this.chart.parent?this._absBaseExtId:this._absSmallBaseExtId},_getExtensionPrefix:function(){return this._extensionPrefix}, -_makeExtensionAbsId:function(a){return i.makeExtensionAbsId(a,this._getExtensionPrefix())},_getExtension:function(a,b){return this.chart._getExtension(this._makeExtensionAbsId(a),b)},_getExtensionAbs:function(a,b){return this.chart._getExtension(a,b)},_getConstantExtension:function(a,b){return this.chart._getConstantExtension(this._makeExtensionAbsId(a),b)},getPvPanel:function(a){var b=this.pvPanel;if(!a)return b;if(!this.parent)throw f.error.operationInvalid("Layers are not possible in a root panel."); -if(!b)throw f.error.operationInvalid("Cannot access layer panels without having created the main panel.");var c=null;if(this._layers)c=this._layers[a];else this._layers={};if(!c){var d=c=this.parent.pvPanel.borderPanel.add(this.type).extend(b.borderPanel);if(b!==b.borderPanel)c=d.add(u.Panel).extend(b);d.borderPanel=d;d.paddingPanel=c;c.paddingPanel=c;c.borderPanel=d;this.initLayerPanel(c,a);this._layers[a]=c}return c},initLayerPanel:function(){},_getV1DimName:function(a){var b=this._v1DimName||(this._v1DimNameCache= -{}),c=b[a];if(c==null){c=(c=this.chart.visualRoles[this._v1DimRoleName[a]])?c.firstDimensionName():"";b[a]=c}return c},_getV1Datum:function(a){return a.datum},context:function(){var a=this._context;if(!a||a.isPinned)a=this._context=new i.visual.Context(this);else Ka.call(a);return a},_isTooltipEnabled:function(){return!this.selectingByRubberband()&&!this.animating()},_getTooltipFormatter:function(a){var b=this.compatVersion()<=1,c=a.format;if(!c){if(!b)return this._summaryTooltipFormatter;c=this.chart.options.v1StyleTooltipFormat; -if(!c)return}if(b)return function(d){return c.call(d.panel,d.getV1Series(),d.getV1Category(),d.getV1Value()||"",d.getV1Datum())};return function(d){return c.call(d,d.scene)}},_summaryTooltipFormatter:function(a){function b(q,s){m.push(""+q+": "+(f.html.escape(s)||" - ")+"
")}function c(q,s){q=e?e.dimensions(s).percentOverParent(l):j.dimensions(s).percent(q.value,l);return n(q)}var d=a.scene;if(!d.datum)return"";var e=d.group,g=e&&e.count()>1,h=d.datum;if(!g&&(!h||h.isNull))return"";var j= -d.data(),l={visible:true},m=[];if(h.isInterpolated)m.push("Interpolation: "+f.html.escape(h.interpolation)+"
");else h.isTrend&&m.push("Trend: "+f.html.escape(h.trendType)+"
");h=j.type;var k=a.panel.stacked===false?null:h.getPlayingPercentVisualRoleDimensionMap(),n=k?a.chart.options.percentValueFormat:null,o=g?e.atoms:d.datum.atoms,p=false;h.sortDimensionNames(f.keys(o)).forEach(function(q){var s=o[q];if(!s.dimension.type.isHidden)if(!g||s.value!=null){p=true;var r=s.label; -if(k&&k.has(q))r+=" ("+c(s,q)+")";b(f.html.escape(s.dimension.type.label),r)}});if(g){p&&m.push("


");m.push("#: "+e._datums.length+"
");h.sortDimensionNames(e.freeDimensionNames()).forEach(function(q){var s=e.dimensions(q);if(!s.type.isHidden){var r=f.html.escape(s.type.label);if(s.type.valueType===Number){s=s.format(s.sum(l));if(k&&k.has(q))s+=" ("+c(null,q)+")";r="∑ "+r}else s=s.atoms(l).map(function(t){return t.label||"- "}).join(", ");b(r,s)}})}return'
'+ -m.join("\n")+"
"},_onClick:function(a){var b=this.clickAction;if(b)this.compatVersion()<=1?this._onV1Click(a,b):b.call(a,a.scene)},_onDoubleClick:function(a){var b=this.doubleClickAction;if(b)this.compatVersion()<=1?this._onV1DoubleClick(a,b):b.call(a,a.scene)},_onV1Click:function(a,b){b.call(a.pvMark,a.getV1Series(),a.getV1Category(),a.getV1Value(),a.event,a.getV1Datum())},_onV1DoubleClick:function(a,b){b.call(a.pvMark,a.getV1Series(),a.getV1Category(),a.getV1Value(),a.event,a.getV1Datum())}, -selectingByRubberband:function(){return this.topRoot._selectingByRubberband},_initRubberBand:function(){var a=this,b=a.chart;if(b.interactive()){var c=b.options.clearSelectionMode==="emptySpaceClick",d=this.chart.selectableByRubberband();if(d||c){var e=b.data,g=a.pvRootPanel||a.pvPanel.paddingPanel;a._getExtensionAbs("base","fillStyle")||g.fillStyle(i.invisibleFill);g.lock("events","all");if(d){this._selectingByRubberband=false;var h,j,l=this.selectBar=(new i.visual.Bar(this,g,{extensionId:"rubberBand", -normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true})).override("defaultStrokeWidth",f.fun.constant(1.5)).override("defaultColor",function(k){return k==="stroke"?"#86fe00":"rgba(203, 239, 163, 0.6)"}).override("interactiveColor",function(k){return k}).pvMark.lock("visible",function(){return!!j}).lock("left",function(){return j.x}).lock("right").lock("top",function(){return j.y}).lock("bottom").lock("width",function(){return j.dx}).lock("height",function(){return j.dy}).lock("cursor").lock("events", -"none"),m;g.intercept("data",function(){var k=this.delegate();k&&k.forEach(function(n){if(n.x==null)n.x=n.y=n.dx=n.dy=0});return k}).event("mousedown",u.Behavior.select().autoRender(false)).event("select",function(k){if(j)j=new u.Shape.Rect(k.x,k.y,k.dx,k.dy);else{if(a.animating())return;if(k.dx*k.dx+k.dy*k.dy<=4)return;j=new u.Shape.Rect(k.x,k.y,k.dx,k.dy);a._selectingByRubberband=true;h||(h=g.toScreenTransform());a.rubberBand=j.apply(h)}l.render()}).event("selectend",function(){if(j){var k=arguments[arguments.length- -1];h||(h=g.toScreenTransform());var n=j.apply(h);j=null;a._selectingByRubberband=false;l.render();try{a._processRubberBand(n,k)}finally{m=new Date}}});c&&g.event("click",function(){if(m)if(new Date-m<300){m=null;return}e.owner.clearSelected()&&b.updateSelections()})}else c&&g.event("click",function(){e.owner.clearSelected()&&b.updateSelections()})}}},_processRubberBand:function(a,b,c){this.rubberBand=a;try{this._onRubberBandSelectionEnd(b,c)}finally{this.rubberBand=null}},_onRubberBandSelectionEnd:function(a, -b){i.debug>=20&&this._log("rubberBand "+i.stringify(this.rubberBand));b=Object.create(b||{});b.toggle=false;var c=this._getDatumsOnRubberBand(a,b);if(c){var d=this.chart;d._updatingSelections(function(){if(!a.ctrlKey&&d.options.ctrlSelectMode){d.data.owner.clearSelected();i.data.Data.setSelected(c,true)}else b.toggle?i.data.Data.toggleSelected(c):i.data.Data.setSelected(c,true)})}},_getDatumsOnRubberBand:function(a,b){a=new f.Map;this._getDatumsOnRect(a,this.rubberBand,b);b=a.values();if(b.length)if((b= -this.chart._onUserSelection(b))&&!b.length)b=null;return b},_getDatumsOnRect:function(a,b,c){this._getOwnDatumsOnRect(a,b,c);var d=this._children;d&&d.forEach(function(e){e._getDatumsOnRect(a,b,c)})},_getOwnDatumsOnRect:function(a,b,c){var d=this;if(!d.isVisible)return false;d=d._getSelectableMarks();if(!d||!d.length)return false;var e=a.count,g=f.get(c,"markSelectionMode"),h=function(l){l.isNull||a.set(l.id,l)},j=function(l){l.selectableByRubberband()&&l.datums().each(h)};d.forEach(function(l){l.eachSceneWithDataOnRect(b, -j,null,g)});return e=1&&isFinite(c)||f.assert("Must be at least 1 and finite");var g=Math.ceil(e/c);g>=1||f.assert("Must be at least 1");var h=this._getCoordinatedRootAxesByScopeType(),j,l,m;if(h){j={};l=function(r,t,A){t=f.array.lazy(j,t);f.array.lazy(t,A).push(r)};m=function(r){h.row&&l(r,"row",r.smallRowIndex);h.column&&l(r,"column", -r.smallColIndex);h.global&&l(r,"global",0)}}for(var k=this._buildSmallChartsBaseOptions(),n=a.constructor,o=0;o0)g.left=b.left;if(e0)g.top=b.top;if(ag?g:e;else if(h>g)h=g;e=e>h?i.text.justify(this.title,h,this.font): -this.title?[this.title]:[];g=u.Text.fontHeight(this.font);var j=e.length*g,l=a.clientSize[c],m=a.desiredClientSize[c];if(m==null)m=j;else if(m>l)m=l;if(j>m){l=Math.max(1,Math.floor(m/g));if(e.length>l){var k=e[l];e.length=l;j=m=l*g;e[l-1]=i.text.trimToWidthB(h,e[l-1]+" "+k,this.font,"..")}}a.lines=e;a.topOffset=(m-j)/2;a.lineSize={width:h,height:g};a.a_width=d;a.a_height=c;b[d]=h;b[c]=m;return b},_createCore:function(a){var b=this._buildScene(a),c={top:0,right:Math.PI/2,bottom:0,left:-Math.PI/2}, -d=i.BasePanel.horizontalAlign[this.align],e=i.BasePanel.leftTopAnchor[this.anchor],g;if(this.compatVersion()<=1)g=function(h){return function(){return h.call(this)}};this.pvLabel=(new i.visual.Label(this,this.pvPanel,{extensionId:"label",wrapper:g})).lock("data",b.lineScenes).pvMark[e](function(h){return a.topOffset+h.vars.size.height/2+this.index*h.vars.size.height}).textAlign(d)[this.anchorOrtho(e)](function(h){switch(this.textAlign()){case "center":return h.vars.size.width/2;case "left":return 0; -case "right":return h.vars.size.width}}).text(function(h){return h.vars.textLines[this.index]}).font(this.font).textBaseline("middle").textAngle(c[this.anchor])},_buildScene:function(a){var b=new i.visual.Scene(null,{panel:this,source:this.chart.data}),c=a.lines;b.vars.size=a.lineSize;b.vars.textLines=c;b.lineScenes=f.array.create(c.length,b);return b},_getExtensionId:f.fun.constant("")});f.type("pvc.TitlePanel",i.TitlePanelAbstract).init(function(a,b,c){c||(c={});if(a.compatVersion()<=1)if(c.titleSize== -null)c.titleSize=25;this._extensionPrefix=!a.parent?"title":"smallTitle";this.base(a,b,c)}).add({font:"14px sans-serif",defaultPaddings:4});f.type("pvc.LegendPanel",i.BasePanel).init(function(a,b,c){this.base(a,b,c);a=i.visual.Interactive;if(this._ibits&a.Interactive)this._ibits|=a.Clickable}).add({pvRule:null,pvDot:null,pvLabel:null,anchor:"bottom",pvLegendPanel:null,textMargin:6,itemPadding:2.5,markerSize:15,font:"10px sans-serif",_calcLayout:function(a){return this._getBulletRootScene().layout(a)}, -_createCore:function(a){var b=a.clientSize;a=this._getBulletRootScene();var c=a.vars.itemPadding,d=a.vars.size,e=this.isAnchorTopOrBottom(),g=e?"top":"left",h=this.anchorOpposite(g),j=this.anchorLength(g),l=this.anchorOrthoLength(g),m=e?"center":"middle",k=e?"left":"top",n=this.anchorOpposite(k),o=0;switch(this.align){case n:o=b[j]-d.width;break;case m:o=(b[j]-d.width)/2;break}this.pvPanel.overflow("hidden");b=this.pvPanel.add(u.Panel).data(a.vars.rows)[k](o)[g](function(){var t=this.sibling();return t? -t[g]+t[l]+c[l]:0})[j](function(t){return t.size.width})[l](function(t){return t.size.height});var p;if(this.compatVersion()<=1)p=function(t){return function(A){return t.call(this,A.vars.value.rawValue)}};this.pvLegendPanel=(new i.visual.Panel(this,b,{extensionId:"panel",wrapper:p,noSelect:false,noHover:true,noClick:false,noClickSelect:true})).lockMark("data",function(t){return t.items}).lock(n,null).lock(h,null).lockMark(k,function(t){t=t.vars.itemPadding;var A=this.sibling();return A?A[k]+A[j]+t[j]: -0}).lockMark("height",function(t){return t.vars.clientSize.height}).lockMark(g,e?function(t){t=t.vars;return t.row.size.height/2-t.clientSize.height/2}:0).lockMark("width",e?function(t){return t.vars.clientSize.width}:function(){return this.parent.width()}).pvMark.def("hidden","false").fillStyle(function(){return this.hidden()=="true"?"rgba(200,200,200,1)":"rgba(200,200,200,0.0001)"});var q=(new i.visual.Panel(this,this.pvLegendPanel)).pvMark.left(0).top(0).right(null).bottom(null).width(function(t){return t.vars.markerSize}).height(function(t){return t.vars.clientSize.height}); -if(i.debug>=20){b.strokeStyle("red");this.pvLegendPanel.strokeStyle("green");q.strokeStyle("blue")}a.childNodes.forEach(function(t){var A=(new i.visual.Panel(this,q)).pvMark.visible(function(x){return x.parent===t});t.renderer().create(this,A,t.extensionPrefix,p)},this);this.pvLabel=(new i.visual.Label(this,q.anchor("right"),{extensionId:"label",wrapper:p})).intercept("textStyle",function(t){var A=this.delegateExtension()||"black";return t.isOn()?A:i.toGrayScale(A,null,undefined,150)}).pvMark.textAlign("left").text(function(t){return t.vars.value.label}).lock("textMargin", -function(t){return t.vars.textMargin-4}).font(function(t){return t.vars.font}).textDecoration(function(t){return t.isOn()?"":"line-through"});if(i.debug>=16){var s=this.font,r=u.Text.fontHeight(s)*2/3;q.anchor("right").add(u.Panel)[this.anchorLength()](0)[this.anchorOrthoLength()](0).fillStyle(null).strokeStyle(null).lineWidth(0).add(u.Line).data(function(t){t=i.text.getLabelBBox(u.Text.measure(t.vars.value.label,s).width,r,"left","middle",0,2).source.points();if(t.length>1)t=t.concat(t[0]);return t}).left(function(t){return t.x}).top(function(t){return t.y}).strokeStyle("red").lineWidth(0.5).strokeDasharray("-")}}, -_onClick:function(a){a=a.scene;f.fun.is(a.execute)&&a.executable()&&a.execute()},_getExtensionPrefix:function(){return"legend"},_getExtensionId:function(){return"area"},_getSelectableMarks:function(){return[this.pvLegendPanel]},_getBulletRootScene:function(){var a=this._rootScene;if(!a)this._rootScene=a=new i.visual.legend.BulletRootScene(null,{panel:this,source:this.chart.data,horizontal:this.isAnchorTopOrBottom(),font:this.font,markerSize:this.markerSize,textMargin:this.textMargin,itemPadding:this.itemPadding}); -return a}});f.type("pvc.CartesianAbstract",i.BaseChart).init(function(a){this.axesPanels={};this.base(a)}).add({_gridDockPanel:null,axesPanels:null,yAxisPanel:null,xAxisPanel:null,secondXAxisPanel:null,secondYAxisPanel:null,yScale:null,xScale:null,_getSeriesRoleSpec:function(){return{isRequired:true,defaultDimension:"series*",autoCreateDimension:true,requireIsDiscrete:true}},_getColorRoleSpec:function(){return{isRequired:true,defaultDimension:"color*",defaultSourceRole:"series",requireIsDiscrete:true}}, -_collectPlotAxesDataCells:function(a,b){this.base(a,b);if(a.option.isDefined("BaseAxis")){var c=f.array.lazy(b,"base");f.array.lazy(c,a.option("BaseAxis")-1).push({plot:a,role:this.visualRole(a.option("BaseRole")),dataPartValue:a.option("DataPart")})}if(a.option.isDefined("OrthoAxis")){c=a.option("Trend");var d=a.option.isDefined("Stacked")?a.option("Stacked"):undefined;b=f.array.lazy(b,"ortho");var e=f.array.to(a.option("OrthoRole")),g={dataPartValue:a.option("DataPart"),isStacked:d,trend:c,nullInterpolationMode:a.option("NullInterpolationMode")}, -h=f.array.lazy(b,a.option("OrthoAxis")-1);e.forEach(function(j){var l=Object.create(g);l.role=this.visualRole(j);h.push(l)},this)}},_addAxis:function(a){this.base(a);switch(a.type){case "base":case "ortho":this.axes[a.orientedId]=a;if(a.v1SecondOrientedId)this.axes[a.v1SecondOrientedId]=a;break}return this},_generateTrendsDataCell:function(a){var b=a.trend;if(b){b=i.trends.get(b.type);var c=[];this._generateTrendsDataCellCore(c,a,b);c.length&&this.data.owner.add(c)}},_generateTrendsDataCellCore:function(){}, -_setAxesScales:function(a){this.base(a);if(!a||this.parent)["base","ortho"].forEach(function(b){(b=this.axesByType[b])&&b.forEach(this._createAxisScale,this)},this)},_createAxisScale:function(a){var b=this.base(a),c=a.type==="ortho";if(c||a.type==="base")if(c&&a.index===1)this.secondScale=b;else a.index||(this[a.orientation+"Scale"]=b);return b},_preRenderContent:function(a){this._createFocusWindow();this._gridDockPanel=new i.CartesianGridDockingPanel(this,this.basePanel,{margins:a.margins,paddings:a.paddings}); -["base","ortho"].forEach(function(b){(b=this.axesByType[b])&&f.query(b).reverse().each(function(c){this._createAxisPanel(c)},this)},this);this._createPlotPanels(this._gridDockPanel,{clickAction:a.clickAction,doubleClickAction:a.doubleClickAction})},_createFocusWindow:function(){if(this.selectableByFocusWindow()){var a,b=this.focusWindow;if(b)a=b._exportData();b=this.focusWindow=new i.visual.CartesianFocusWindow(this);a&&b._importData(a);b._initFromOptions()}else this.focusWindow&&delete this.focusWindow}, -_createAxisPanel:function(a){if(a.option("Visible")){var b,c=a.option("Title");f.empty(c)||(b=new i.AxisTitlePanel(this,this._gridDockPanel,a,{title:c,font:a.option("TitleFont")||a.option("Font"),anchor:a.option("Position"),align:a.option("TitleAlign"),margins:a.option("TitleMargins"),paddings:a.option("TitlePaddings"),titleSize:a.option("TitleSize"),titleSizeMax:a.option("TitleSizeMax")}));c=new i.AxisPanel(this,this._gridDockPanel,a,{anchor:a.option("Position"),size:a.option("Size"),sizeMax:a.option("SizeMax"), -clickAction:a.option("ClickAction"),doubleClickAction:a.option("DoubleClickAction"),useCompositeAxis:a.option("Composite"),font:a.option("Font"),labelSpacingMin:a.option("LabelSpacingMin"),grid:a.option("Grid"),gridCrossesMargin:a.option("GridCrossesMargin"),ruleCrossesMargin:a.option("RuleCrossesMargin"),zeroLine:a.option("ZeroLine"),desiredTickCount:a.option("DesiredTickCount"),showTicks:a.option("Ticks"),showMinorTicks:a.option("MinorTicks")});if(b)c.titlePanel=b;this.axesPanels[a.id]=c;this.axesPanels[a.orientedId]= -c;if(a.index<=1&&a.v1SecondOrientedId)this[a.v1SecondOrientedId+"AxisPanel"]=c;return c}},_onLaidOut:function(){this.plotPanelList&&this.plotPanelList[0]&&["base","ortho"].forEach(function(a){(a=this.axesByType[a])&&a.forEach(this._setCartAxisScaleRange,this)},this)},_setCartAxisScaleRange:function(a){var b=this.plotPanelList[0]._layoutInfo.clientSize;a.setScaleRange(a.orientation==="x"?b.width:b.height);return a.scale},_getAxesRoundingPaddings:function(){function a(e,g,h){var j=c[e];if(j==null|| -g>j){c[e]=g;c[e+"Locked"]=h}else if(h)c[e+"Locked"]=h}function b(e){if(e){var g=e.getScaleRoundingPaddings();if(g){e=e.orientation==="x";a(e?"left":"bottom",g.begin,g.beginLocked);a(e?"right":"top",g.end,g.endLocked)}}}var c={},d=this.axesByType;["base","ortho"].forEach(function(e){(e=d[e])&&e.forEach(b)});return c},markEventDefaults:{strokeStyle:"#5BCBF5",lineWidth:"0.5",textStyle:"#5BCBF5",verticalOffset:10,verticalAnchor:"bottom",horizontalAnchor:"right",forceHorizontalAnchor:false,horizontalAnchorSwapLimit:80, -font:"10px sans-serif"},markEvent:function(a,b,c){var d=this,e=d.axes.base,g=d.axes.ortho,h=e.scale,j=d.data.owner.dimensions(e.role.grouping.firstDimensionName());if(e.isDiscrete()){d._warn("Can only mark events in charts with a continuous base scale.");return d}c=$.extend({},d.markEventDefaults,c);a=j.read(a,b);b=h(a.value);h=h.range();e=h[1];if(be){this._warn("Cannot mark event because it is outside the base scale's domain.");return this}h=this.plotPanelList[0].pvPanel;g=g.scale.range()[1]; -j=c.horizontalAnchor;if(!c.forceHorizontalAnchor){var l=j==="right";e=l?e-b:b;var m=u.Text.measure(a.label,c.font).width;if(e0,R;C=false;var E;G=0;for(N=B.length;G0){s&&q._log("SIDE Child #"+(G+1)+" changed normal paddings"); -E=true}else i.debug>=2&&q._warn("SIDE Child #"+(G+1)+" changed paddings but no more iterations possible.");if((R&K)!==0){V=true;b(0);return false}if(E)return true}}finally{s&&q._groupEnd()}G++}if(C){s&&q._log("Restarting due to overflowPaddings change");return false}G=0;for(N=w.length;G0){i.debug>=5&&q._log("FILL Child #"+(G+1)+" increased paddings");E=true}else i.debug>=2&&q._warn("FILL Child #"+(G+1)+" increased paddings but no more iterations possible."); -if((R&K)!==0){V=true;b(0);return false}if(E)return true}}finally{s&&q._groupEnd()}G++}return false}finally{s&&q._groupEnd()}}function c(D,C){for(var G=0;D--;){if(C(D,G)===false)return true;G++}return false}function d(D){var C=D.anchor;if(C)if(C==="fill"){w.push(D);D=D.paddings.resolve(z.referenceSize);t=F.resolvedMax(t,D)}else{f.hasOwn(v,C)||f.fail.operationInvalid("Unknown anchor value '{0}'",[C]);B.push(D)}}function e(D,C){s&&q._group("SIDE Child #"+(C+1));try{C=0;var G=D.anchor;z.paddings=k(G, -t);D.layout(new M(A),z);if(D.isVisible){C|=n(G,t,D);j(G,D);l(G,D)}return C}finally{s&&q._groupEnd()}}function g(D,C){var G=0,N=D.anchor;z.paddings=k(N,t);z.canChange=C;D.layout(new M(A),z);if(D.isVisible){G|=n(N,t,D,C);j(N,D);m(D,N)}return G}function h(D,C){var G=0;if(D.isVisible){var N=D.anchor,Q=y[N],R=x[N];Q=new M(f.set({},Q,A[Q],R,D[R]));z.paddings=k(N,t);z.canChange=C;D.layout(Q,z);if(D.isVisible)(G=n(N,t,D,C)|o(N,a.paddings,D,C))||m(D,D.align)}return G}function j(D,C){var G;if(D==="fill"){D= -"left";G=r.left+A.width/2-C.width/2}else G=r[D];C.setPosition(f.set({},D,G))}function l(D,C){var G=x[D];C=C[G];r[D]+=C;A[G]-=C}function m(D,C){var G;if(C==="fill")C="middle";var N;switch(C){case "top":case "bottom":case "left":case "right":G=C;N=r[G];break;case "middle":G="bottom";N=r.bottom+A.height/2-D.height/2;break;case "center":G="left";N=r.left+A.width/2-D.width/2;break}D.setPosition(f.set({},G,N))}function k(D,C){var G=new F;p(D).forEach(function(N){G.set(N,C[N])});return G}function n(D,C, -G,N){var Q=G._layoutInfo.requestPaddings,R=0;if(Q){if(s&&i.debug>=10){q._log("=> clientSize="+i.stringify(G._layoutInfo.clientSize));q._log("<= requestPaddings="+i.stringify(Q))}p(D).forEach(function(E){var P=C[E]||0,U=Math.floor(1E4*(Q[E]||0))/1E4,T=U-P;P=Math.max(1,Math.abs(0.01*P));if(T!==0&&Math.abs(T)>=P)if(N){R|=S;C[E]=U;s&&q._log("Changed padding "+E+" <- "+U)}else i.debug>=2&&q._warn("CANNOT change but child wanted to: "+E+"="+U)});if(R){D=F.names.map(function(E){return(C[E]||0).toFixed(0)}).join("|"); -if(f.hasOwn(H,D)){i.debug>=2&&q._warn("LOOP detected!!!!");R|=K}else H[D]=true;C.width=C.left+C.right;C.height=C.top+C.bottom}}return R}function o(D,C,G,N){var Q=G._layoutInfo.overflowPaddings||W,R=0;s&&i.debug>=10&&q._log("<= overflowPaddings="+i.stringify(Q));p(D).forEach(function(E){if(Q.hasOwnProperty(E)){var P=C[E]||0,U=Math.floor(1E4*(Q[E]||0))/1E4;U-=r[E];var T=U-P;P=Math.max(1,Math.abs(0.05*P));if(T>=P)if(N){R|=J;C[E]=U;s&&q._log("changed overflow padding "+E+" <- "+U)}else i.debug>=2&&q._warn("CANNOT change overflow padding but child wanted to: "+ -E+"="+U)}});if(R){C.width=C.left+C.right;C.height=C.top+C.bottom}return R}function p(D){switch(D){case "left":case "right":return F.vnames;case "top":case "bottom":return F.hnames;case "fill":return F.names}}var q=this;if(q._children){var s=i.debug>=5,r=new F(0),t=new F(0),A=f.copyOwn(a.clientSize),x=i.BasePanel.orthogonalLength,v=i.BasePanel.relativeAnchor,y=i.BasePanel.parallelLength,z={force:true,referenceSize:a.clientSize},w=[],B=[],H={},K=1,S=2,J=4,W=new F,V=false;s&&q._group("CCC GRID LAYOUT clientSize = "+ -i.stringify(A));try{this._children.forEach(d);s&&q._group("Phase 1 - Determine MARGINS and FILL SIZE from SIDE panels");try{B.forEach(e)}finally{if(s){q._groupEnd();q._log("Final FILL margins = "+i.stringify(r));q._log("Final FILL border size = "+i.stringify(A))}}s&&q._group("Phase 2 - Determine COMMON PADDINGS");try{c(9,b)}finally{if(s){q._groupEnd();q._log("Final FILL clientSize = "+i.stringify({width:A.width-t.width,height:A.height-t.height}));q._log("Final COMMON paddings = "+i.stringify(t))}}a.gridMargins= -new F(r);a.gridPaddings=new F(t);a.gridSize=new M(A)}finally{s&&q._groupEnd()}}}});f.type("pvc.CartesianGridDockingPanel",i.GridDockingPanel).init(function(a,b,c){this.base(a,b,c);this._plotBgPanel=new i.PlotBgPanel(a,this)}).add({_getExtensionId:function(){return!this.chart.parent?"content":"smallContent"},_createCore:function(a){var b=this.chart,c=b.axes,d=c.x,e=c.y;if(d.option("Grid"))this.xGridRule=this._createGridRule(d);if(e.option("Grid"))this.yGridRule=this._createGridRule(e);this.base(a); -b.focusWindow&&this._createFocusWindow(a);if(b.compatVersion()<=1?!!(d.option("EndLine")||e.option("EndLine")):f.get(b.options,"plotFrameVisible",true))this.pvFrameBar=this._createFrame(a,c);if(d.scaleType!=="discrete"&&d.option("ZeroLine"))this.xZeroLine=this._createZeroLine(d,a);if(e.scaleType!=="discrete"&&e.option("ZeroLine"))this.yZeroLine=this._createZeroLine(e,a)},_createGridRule:function(a){var b=a.scale;if(!b.isNull){var c=a.role.grouping.isDiscrete(),d=this._getAxisGridRootScene(a);if(d){var e= -this._layoutInfo.gridMargins,g=this._layoutInfo.gridPaddings,h=a.orientation==="x"?"left":"bottom",j=this.anchorLength(h),l=this.anchorOrtho(h),m=this.anchorOpposite(l),k=e[h]+g[h];g=e[l];e=e[m];d=d.leafs().array();var n=d.length;c&&n&&d.push(d[n-1]);var o;if(this.compatVersion()<=1)o=function(q){return function(s){return q.call(this,s.vars.tick.rawValue)}};a=(new i.visual.Rule(this,this.pvPanel,{extensionId:a.extensionPrefixes.map(function(q){return q+"Grid"}),wrapper:o})).lock("data",d).lock(j, -null).override("defaultColor",function(){return u.color("#f0f0f0")}).pvMark.lineWidth(1).antialias(true)[l](g)[m](e).zOrder(-12).events("none");if(c){var p=b.range().step/2;a.lock(h,function(q){return k+b(q.vars.tick.value)+(this.index===n?p:-p)})}else a.lock(h,function(q){return k+b(q.vars.tick.value)});return a}}},_getAxisGridRootScene:function(a){var b=this.data,c=a.isDiscrete();if(c)b=a.role.flatten(b,{visible:true});var d=new i.visual.CartesianAxisRootScene(null,{panel:this,source:b});c?b._children.forEach(function(e){new i.visual.CartesianAxisTickScene(d, -{source:e,tick:e.value,tickRaw:e.rawValue,tickLabel:e.label})}):(a.ticks||a.calcContinuousTicks()).forEach(function(e){new i.visual.CartesianAxisTickScene(d,{tick:e,tickRaw:e,tickLabel:a.scale.tickFormat(e)})},this);return d},_createFrame:function(a,b){if(!(b.base.scale.isNull||b.ortho.scale.isNull&&(!b.ortho2||b.ortho2.scale.isNull))){var c=a.gridMargins;a=c.left;b=c.right;var d=c.top;c=c.bottom;var e=[];if(this.compatVersion()<=1){e.push("xAxisEndLine");e.push("yAxisEndLine")}e.push("plotFrame"); -return(new i.visual.Panel(this,this.pvPanel,{extensionId:e})).pvMark.lock("left",a).lock("right",b).lock("top",d).lock("bottom",c).lock("fillStyle",null).events("none").strokeStyle("#666666").lineWidth(1).antialias(false).zOrder(-8)}},_createZeroLine:function(a,b){var c=a.scale;if(!c.isNull){var d=c.domain();if(d[0]*d[1]<-1.0E-12){d=a.orientation==="x"?"left":"bottom";var e=this.anchorLength(d),g=this.anchorOrtho(d),h=this.anchorOpposite(g),j=b.gridMargins;b=j[d]+b.gridPaddings[d]+c(0);c=j[g];j=j[h]; -var l=new i.visual.Scene(null,{panel:this});return(new i.visual.Rule(this,this.pvPanel,{extensionId:a.extensionPrefixes.map(function(m){return m+"ZeroLine"})})).lock("data",[l]).lock(e,null).lock(g,c).lock(h,j).lock(d,b).override("defaultColor",function(){return u.color("#666666")}).pvMark.events("none").lineWidth(1).antialias(true).zOrder(-9)}}},_createFocusWindow:function(a){function b(){J[y]=0-w[q];J[z]=H+w[q]+w[A]}function c(){var E=arguments[arguments.length-1].drag.phase==="end";g._selectingByRubberband= -!E;C.render();G.render();var P=J[x],U=J[x]+J[v];if(!o){var T=B-P;P=B-U;U=T}j._updatePosition(P,U,E,true)}function d(E,P){var U=E.m,T=U[Q],aa,ba=J[R],ha;switch(P){case "new":aa=0;ha="begin";break;case "resize-begin":aa=ba;ha="begin";break;case "move":aa=ba;ha="begin";break;case "resize-end":aa=T-J[Q];ha="end";break}T={type:P,target:ha,point:T,length:aa,length0:ba,min:E.min[Q],max:E.max[Q],minView:0,maxView:B};j._constraintPosition(T);U[Q]=T.point;switch(P){case "resize-begin":T.max=Math.min(T.max, -J[Q]+J[R]);break;case "resize-end":T.min=Math.max(T.min,J[Q]);break}E.min[Q]=T.min;E.max[Q]=T.max}var e=this,g=e.topRoot,h=e.chart,j=h.focusWindow.base,l=j.axis,m=l.scale;if(!m.isNull){var k=j.option("Resizable"),n=j.option("Movable");l=l.isDiscrete();var o=h.isOrientationVertical(),p=o?"left":"top",q=o?"top":"left",s=e.anchorOrthoLength(p),r=e.anchorOpposite(p),t=e.anchorOrthoLength(q),A=e.anchorOpposite(q),x=o?"x":"y",v="d"+x,y=o?"y":"x",z="d"+y;h=a.gridMargins;var w=a.gridPaddings;h={left:h.left+ -w.left,right:h.right+w.right,top:h.top+w.top,bottom:h.bottom+w.bottom};h.width=h.left+h.right;h.height=h.top+h.bottom;a=a.clientSize;var B=a[s]-h[s],H=a[t]-h[t],K=w[p],S=w[r],J=new i.visual.Scene(null,{panel:this});a=l?m.range().step:0;l=a/2;J[x]=m(j.begin)-l;J[v]=a+(m(j.end)-l)-J[x];b();var W=function(E){return function(){return J[E]}},V=function(){return Math.max(0,Math.min(B,J[x]))},D=function(){var E=V(),P=J[x]+J[v];P=Math.max(0,Math.min(B,P));return P-E};m=function(E,P){return(new i.visual.Bar(e, -E,{extensionId:P,normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true,showsInteraction:false})).pvMark.lock("data").lock("visible").lock(p,V).lock(s,D).lock(q,W(y)).lock(t,W(z)).lock(A).lock(r).sign};var C=this._plotBgPanel.pvPanel.borderPanel;C.lock("data",[J]);n&&k?C.paddingPanel.lock("events","all").lock("cursor","crosshair").event("mousedown",u.Behavior.select().autoRender(false).collapse(o?"y":"x").positionConstraint(function(E){return d(E,E.phase==="start"? -"new":"resize-end")})).event("selectstart",function(E){b();c(E)}).event("select",c).event("selectend",c):C.paddingPanel.events("all");a=m(C.paddingPanel,"focusWindowBg").override("defaultColor",function(){return i.invisibleFill}).pvMark;n?a.lock("events","all").lock("cursor","move").event("mousedown",u.Behavior.drag().autoRender(false).collapse(o?"y":"x").positionConstraint(function(E){d(E,"move")})).event("drag",c).event("dragend",c):a.events("none");var G=(new i.visual.Panel(e,e.pvPanel)).pvMark.lock("data", -[J]).lock("visible").lock("fillStyle",i.invisibleFill).lock("left",h.left).lock("right",h.right).lock("top",h.top).lock("bottom",h.bottom).lock("zOrder",10).lock("events",function(){var E=J.drag;return E&&E.phase!=="end"?"all":"none"}).lock("cursor",function(){var E=J.drag;return E&&E.phase!=="end"?E.type==="drag"||E.type==="select"&&!k?"move":o?"ew-resize":"ns-resize":null}).antialias(false);(new i.visual.Bar(e,G,{extensionId:"focusWindowBaseCurtain",normalStroke:true,noHover:true,noSelect:true, -noClick:true,noDoubleClick:true,noTooltip:true,showsInteraction:false})).override("defaultColor",function(E){return E==="stroke"?null:"rgba(20, 20, 20, 0.1)"}).pvMark.lock("data",[J,J]).lock("visible").lock("events","none").lock(p,function(){return!this.index?-K:V()+D()}).lock(r,function(){return!this.index?null:-S}).lock(s,function(){return!this.index?K+V():null}).lock(q,W(y)).lock(t,W(z)).lock(A);var N=m(G,"focusWindow").override("defaultColor",function(){return null}).pvMark.lock("events","none"); -n=function(E){var P=E==="left"||E==="top"?"begin":"end",U="linear-gradient(to "+e.anchorOpposite(E)+", rgba(20, 20, 20, 0.1), #444 90%)",T=(new i.visual.Bar(e,N.anchor(E),{extensionId:j.id+"Grip"+f.firstUpperCase(P),normalStroke:true,noHover:true,noSelect:true,noClick:true,noDoubleClick:true,noTooltip:true,showsInteraction:false})).override("defaultColor",function(ba){return ba==="stroke"?null:U}).pvMark.lock("data").lock("visible")[q](J[y])[t](J[z]);if(k){var aa="resize-"+P;T.lock("events","all")[s](5).cursor(o? -"ew-resize":"ns-resize").event("mousedown",u.Behavior.resize(E).autoRender(false).positionConstraint(function(ba){d(ba,aa)}).preserveOrtho(true)).event("resize",c).event("resizeend",c)}else T.events("none")[s](1);return T};n(p);n(r);var Q=x,R=v}},_getDatumsOnRect:function(a,b,c){var d=this.chart,e=d.axesPanels.x,g=d.axesPanels.y,h,j;if(e){h=new f.Map;e._getDatumsOnRect(h,b,c);h.count||(h=null)}if(g){j=new f.Map;g._getOwnDatumsOnRect(j,b,c);j.count||(j=null)}if(h&&j){h.intersect(j,a);c.toggle=true}else if(h)a.copy(h); -else j?a.copy(j):d.plotPanelList.forEach(function(l){l._getDatumsOnRect(a,b,c)},this)}});f.type("pvc.CartesianAbstractPanel",i.PlotPanel).init(function(a,b,c,d){function e(n){j[n.type]=n;j[n.orientedId]=n;if(n.v1SecondOrientedId)j[n.v1SecondOrientedId]=n}function g(n,o){var p=l[n];if(p==null||o>p){m=true;l[n]=o}}function h(n){var o=n&&n.option("Offset");if(o!=null&&o>0&&o<1)if(n.orientation==="x"){g("left",o);g("right",o)}else{g("top",o);g("bottom",o)}}this.base(a,b,c,d);var j=this.axes;e(a._getAxis("base", -c.option("BaseAxis")-1));e(a._getAxis("ortho",c.option("OrthoAxis")-1));var l={},m=false,k=a.axesByType;["base","ortho"].forEach(function(n){(n=k[n])&&n.forEach(h)});if(m)this.offsetPaddings=l}).add({offsetPaddings:null,_calcLayout:function(a){a.requestPaddings=this._calcRequestPaddings(a)},_calcRequestPaddings:function(a){var b,c=this.offsetPaddings;if(c){var d=this.chart._getAxesRoundingPaddings(),e=a.clientSize,g=a.paddings;F.names.forEach(function(h){var j=i.BasePanel.orthogonalLength[h],l=e[j]; -j=l+g[j];if(!d[h+"Locked"]){j=j*(c[h]||0);l=l*(d[h]||0);(b||(b={}))[h]=Math.max(j-l,0)}},this)}return b},_createCore:function(){this.pvPanel.zOrder(-10);var a=this.chart.options.leafContentOverflow||"auto";(a==="auto"?f.query(["ortho","base"]).select(function(b){return this.axes[b]},this).any(function(b){return b.option("FixedMin")!=null||b.option("FixedMax")!=null}):a==="hidden")&&this.pvPanel.borderPanel.overflow("hidden")}});f.type("pvc.PlotBgPanel",i.BasePanel).init(function(a,b,c){this.base(a, -b,c)}).add({anchor:"fill",_getExtensionId:function(){return"plotBg"},_createCore:function(a){this.pvPanel.borderPanel.lock("zOrder",-13).antialias(false);this.base(a)}});f.type("pvc.CategoricalAbstract",i.CartesianAbstract).init(function(a){this.base(a);if(a=this.parent)this._catRole=a._catRole}).add({_initVisualRoles:function(){this.base();this._catRole=this._addVisualRole("category",this._getCategoryRoleSpec())},_getCategoryRoleSpec:function(){return{isRequired:true,defaultDimension:"category*", -autoCreateDimension:true}},_generateTrendsDataCellCore:function(a,b,c){function d(s){var r=n?null:function(v){return v.atoms[k].value},t=function(v){if((v=p._childrenByKey[v.key])&&s)v=v._childrenByKey[s.key];return v?v.dimensions(m).sum(o):null};r=f.create(j,{rows:f.query(q),x:r,y:t});var A=c.model(r),x=p.owner.dimensions(l).intern(this.root._firstTrendAtomProto);A&&q.forEach(function(v,y){y=A.sample(n?y:v.atoms[k].value,t(v),y);if(y!=null){var z=p._childrenByKey[v.key];v=z||v;if(s)if(z=z&&z._childrenByKey[s.key])z= -Object.create(z._datums[0].atoms);else{z=Object.create(v._datums[0].atoms);f.copyOwn(z,s.atoms)}else z=Object.create(v._datums[0].atoms);z[m]=y;z[l]=x;a.push(f.set(new i.data.Datum(v.owner,z),"isVirtual",true,"isTrend",true,"trendType",c.type))}},this)}var e=this._serRole,g=this._catRole,h=b.role,j=b.trend;this._warnSingleContinuousValueRole(h);var l=this._dataPartRole.firstDimensionName(),m=h.firstDimensionName(),k,n=g.isDiscrete();n||(k=g.firstDimensionName());var o={zeroIfNone:false};h={ignoreNulls:false}; -var p=this.visibleData(b.dataPartValue);b=this.visibleData(null,h);var q=g.flatten(b,h)._children;f.scope(function(){return e&&e.isBound()?e.flatten(p).children():f.query([null])}).each(d,this)},_interpolateDataCell:function(a){var b=a.nullInterpolationMode;if(b){var c;switch(a.nullInterpolationMode){case "linear":c=i.data.LinearInterpolationOper;break;case "zero":c=i.data.ZeroInterpolationOper;break;case "none":break;default:throw f.error.argumentInvalid("nullInterpolationMode",""+b);}if(c){this._warnSingleContinuousValueRole(a.role); -b=this.visibleData(a.dataPartValue);if(b.childCount()>0){var d=this.visibleData(null,{ignoreNulls:false});(new c(d,b,this._catRole,this._serRole,a.role,true)).interpolate()}}}},_createVisibleData:function(a,b){var c=this._serRole&&this._serRole.flattenedGrouping(),d=this._catRole.flattenedGrouping();a=this.partData(a);var e=f.get(b,"ignoreNulls");b=f.get(b,"inverted",false);e={visible:true,isNull:e?false:null};return c?a.groupBy(b?[c,d]:[d,c],e):a.groupBy(d,e)},_getContinuousVisibleCellExtent:function(a, -b){var c=b.role;switch(c.name){case "series":case "category":return this.base(a,b)}this._warnSingleContinuousValueRole(c);var d=b.dataPartValue,e=c.firstDimensionName();c=this.visibleData(d);var g=a.scaleUsesAbs();if(a.type!=="ortho"||!b.isStacked)return c.leafs().select(function(h){h=h.dimensions(e).sum();return g&&h<0?-h:h}).range();return c.children().select(function(h){var j=this._getStackedCategoryValueExtent(h,e,g);if(j)return{range:j,group:h}},this).where(f.notNully).reduce(function(h,j){return this._reduceStackedCategoryValueExtent(h, -j.range,j.group)}.bind(this),null)},_getStackedCategoryValueExtent:function(a,b,c){var d=null,e=null;a.children().select(function(g){g=g.dimensions(b).sum();return c&&g<0?-g:g}).each(function(g){if(g!=null)if(g>=0)d+=g;else e+=g});if(d==null&&e==null)return null;return{max:d||0,min:e||0}},_reduceStackedCategoryValueExtent:function(a,b){return i.unionExtents(a,b)},_coordinateSmallChartsLayout:function(a){this.base(a);var b=0,c,d=null,e={};this.children.forEach(function(g){g.basePanel.layout();var h, -j=g.titlePanel;if(j){c||(c=j.anchorOrthoLength());h=j[c];if(h>b)b=h}var l=g.axesPanels;d||(d=f.query(f.ownKeys(l)).where(function(m){return m===l[m].axis.id}).select(function(m){e[m]={axis:0,title:0};return m}).array());d.forEach(function(m){var k=l[m];m=e[m];var n=k.axis.orientation==="x"?"height":"width";h=k[n];if(h>m.axis)m.axis=h;if(k=k.titlePanel){h=k[n];if(h>m.title)m.title=h}})},this);this.children.forEach(function(g){if(b>0){var h=g.titlePanel;h.size=h.size.clone().set(c,b)}var j=g.axesPanels; -d.forEach(function(l){var m=j[l];l=e[l];var k=m.axis.orientation==="x"?"height":"width";m.size=m.size.clone().set(k,l.axis);if(m=m.titlePanel)m.size=m.size.clone().set(k,l.title)});g.basePanel.invalidateLayout()},this)},defaults:{orthoAxisOrdinal:false}});f.type("pvc.CategoricalAbstractPanel",i.CartesianAbstractPanel).init(function(a,b,c,d){this.base(a,b,c,d);this.stacked=c.option("Stacked")});f.type("pvc.AxisPanel",i.BasePanel).init(function(a,b,c,d){d=f.create(d,{anchor:c.option("Position")});var e= -d.anchor||this.anchor;this.axis=c;this.base(a,b,d);this.roleName=c.role.name;this.isDiscrete=c.role.isDiscrete();this._extensionPrefix=c.extensionPrefixes;if(this.labelSpacingMin==null)this.labelSpacingMin=this.isDiscrete?0.25:1.5;if(this.showTicks==null)this.showTicks=!this.isDiscrete;if(d.font===undefined)if(a=this._getConstantExtension("label","font"))this.font=a;if(d.tickLength===undefined){d=+this._getConstantExtension("ticks",this.anchorOrthoLength(e));if(!isNaN(d)&&isFinite(d))this.tickLength= -d}}).add({pvRule:null,pvTicks:null,pvLabel:null,pvRuleGrid:null,pvScale:null,isDiscrete:false,roleName:null,axis:null,anchor:"bottom",tickLength:6,scale:null,ruleCrossesMargin:true,font:"9px sans-serif",labelSpacingMin:null,desiredTickCount:null,showMinorTicks:true,showTicks:null,hiddenLabelText:"\u00b7",_isScaleSetup:false,_createLogInstanceId:function(){return this.base()+" - "+this.axis.id},getTicks:function(){return this._layoutInfo&&this._layoutInfo.ticks},_calcLayout:function(a){var b=this.axis.scale; -if(!this._isScaleSetup){this.scale=this.pvScale=b;this.extend(b,"scale");this._isScaleSetup=true}if(b.isNull)a.axisSize=0;else this._calcLayoutCore(a);return this.createAnchoredSize(a.axisSize,a.clientSize)},_calcLayoutCore:function(a){var b=a.desiredClientSize[this.anchorOrthoLength()];a.axisSize=b;if(this.isDiscrete&&this.useCompositeAxis){if(a.axisSize==null)a.axisSize=50}else{this._readTextProperties(a);this._calcTicks();if(this.scale.type==="discrete")this._tickIncludeModulo=this._calcDiscreteTicksIncludeModulo(); -this._calcAxisSizeFromLabel(a);if(a.axisSize==null)a.axisSize=a.requiredAxisSize;this._calcMaxTextLengthThatFits();this._calcOverflowPaddings()}},_calcAxisSizeFromLabel:function(a){this._calcTicksLabelBBoxes(a);this._calcAxisSizeFromLabelBBox(a)},_readTextProperties:function(a){var b=this._getExtension("label","textAngle");a.isTextAngleFixed=b!=null;a.textAngle=f.number.as(b,0);a.textMargin=f.number.as(this._getExtension("label","textMargin"),3);b=this._getExtension("label","textAlign");if(typeof b!== -"string")b=this.isAnchorTopOrBottom()?"center":this.anchor=="left"?"right":"left";a.textAlign=b;b=this._getExtension("label","textBaseline");if(typeof b!=="string")switch(this.anchor){case "right":case "left":case "center":b="middle";break;case "bottom":b="top";break;default:b="bottom"}a.textBaseline=b},_calcAxisSizeFromLabelBBox:function(a){var b=a.maxLabelBBox,c=this.tickLength+this._getLabelBBoxQuadrantLength(b,this.anchor);b.sourceAngle===0&&this.isAnchorTopOrBottom()||(c+=this.tickLength);a.requiredAxisSize= -c},_getLabelBBoxQuadrantLength:function(a,b){var c;switch(b){case "left":c=-a.x;break;case "right":c=a.x2;break;case "top":c=-a.y;break;case "bottom":c=a.y2;break}return Math.max(c,0)},_calcOverflowPaddings:function(){if(this._layoutInfo.canChange)this._calcOverflowPaddingsFromLabelBBox();else i.debug>=2&&this._warn("Layout cannot change. Skipping calculation of overflow paddings.")},_calcOverflowPaddingsFromLabelBBox:function(){var a=null,b=this,c=b._layoutInfo,d=c.ticks;if(d.length){var e=c.ticksBBoxes, -g=c.paddings,h=b.isAnchorTopOrBottom(),j=h?"left":"bottom",l=h?"right":"top",m=b.scale,k=m.type==="discrete",n=c.clientSize[b.anchorLength()];this.axis.setScaleRange(n);var o=function(p,q,s,r){p=b._getLabelBBoxQuadrantLength(p,q);if(p>1){r=m(k?d[r].value:d[r]);r=s?r-p:r+p;s=Math.max(0,s?-r:r-n);if(s>1){s-=g[q]||0;if(s>1){if(k)s*=1.05;if(a){r=a[q];if(r==null||r=6&&a&&b._log("OverflowPaddings = "+i.stringify(a))}c.overflowPaddings= -a},_calcMaxTextLengthThatFits:function(){var a=this._layoutInfo;if(this.compatVersion()<=1)a.maxTextWidth=null;else{var b=a.clientSize[this.anchorOrthoLength()],c=Math.min(a.axisSize,b);if(c>=a.requiredAxisSize-this.tickLength)a.maxTextWidth=null;else{b=a.maxLabelBBox;c=c-2*this.tickLength;var d,e;switch(this.anchor){case "left":e=u.vector(0,1);d=u.vector(-c,0);break;case "right":e=u.vector(0,1);d=u.vector(c,0);break;case "top":e=u.vector(1,0);d=u.vector(0,-c);break;case "bottom":e=u.vector(1,0); -d=u.vector(0,c);break}var g=d.norm(),h=b.source.points(),j=h[0],l=h[1],m=h[2];h=h[3];var k=m.minus(h),n=l.minus(j),o=u.SvgScene.lineIntersect;n=o(d,e,j,n);d=o(d,e,h,k);o=e=b.sourceTextWidth;var p=n.minus(j),q=p.length();if(q<=e&&p.dot(k)>=0)o=j.dot(g)=0)o=h.dot(g)=3&&this._log("Trimming labels' text at length "+ -o.toFixed(2)+"px maxOrthoLength="+c.toFixed(2)+"px")}}},_calcTicks:function(){var a=this._layoutInfo;a.textHeight=u.Text.fontHeight(this.font)*2/3;a.maxTextWidth=null;this.axis.setTicks(null);switch(this.scale.type){case "discrete":this._calcDiscreteTicks();break;case "timeSeries":this._calcTimeSeriesTicks();break;case "numeric":this._calcNumberTicks(a);break;default:throw f.error.operationInvalid("Undefined axis scale type");}this.axis.setTicks(a.ticks);this.axis.setScaleRange(a.clientSize[this.anchorLength()]); -a.maxTextWidth==null&&this._calcTicksTextLength(a)},_calcDiscreteTicks:function(){var a=this._layoutInfo,b=this.axis.role,c=b.flatten(this.data,{visible:true});a.data=c;a.ticks=c._children;var d,e;b=b.grouping;if(b.isSingleDimension&&(e=b.firstDimensionType())&&e.valueType===Date)if((e=c.dimensions(e.name).extent())&&e.min!==e.max){var g=new u.Scale.linear(e.min.value,e.max.value);g.ticks();(d=this.axis.option("TickFormatter"))&&g.tickFormatter(d);d=function(h){return g.tickFormat(h.value)}}d||(d= -function(h){return h.absLabel});a.ticksText=c._children.map(d);this._clearTicksTextDeps(a)},_clearTicksTextDeps:function(a){a.maxTextWidth=a.ticksTextLength=a.ticksBBoxes=null},_calcTimeSeriesTicks:function(){this._calcContinuousTicks(this._layoutInfo)},_calcNumberTicks:function(){var a=this.desiredTickCount;if(a==null){if(this.isAnchorTopOrBottom()){this._calcNumberHTicks();return}a=this._calcNumberVDesiredTickCount()}this._calcContinuousTicks(this._layoutInfo,a)},_calcContinuousTicks:function(a, -b){this._calcContinuousTicksValue(a,b);this._calcContinuousTicksText(a)},_calcContinuousTicksValue:function(a,b){a.ticks=this.axis.calcContinuousTicks(b);if(i.debug>4){this._log("DOMAIN: "+i.stringify(this.scale.domain()));this._log("TICKS: "+i.stringify(a.ticks))}},_calcContinuousTicksText:function(a){var b=a.ticksText=a.ticks.map(function(c){return this.scale.tickFormat(c)},this);this._clearTicksTextDeps(a);return b},_calcTicksTextLength:function(a){var b=0,c=this.font,d=a.ticksText||this._calcContinuousTicksText(a); -d=a.ticksTextLength=d.map(function(e){e=u.Text.measure(e,c).width;if(e>b)b=e;return e});a.maxTextWidth=b;a.ticksBBoxes=null;return d},_calcTicksLabelBBoxes:function(a){var b=this,c=b._layoutInfo,d=a.ticksTextLength||b._calcTicksTextLength(a),e,g=c.maxTextWidth;a.ticksBBoxes=d.map(function(h){var j=b._calcLabelBBox(h);if(!e&&h===g)e=j;return j},b);c.maxLabelBBox=e},_calcLabelBBox:function(a){var b=this._layoutInfo;return i.text.getLabelBBox(a,b.textHeight,b.textAlign,b.textBaseline,b.textAngle,b.textMargin)}, -_calcDiscreteTicksIncludeModulo:function(){var a=this.axis.option("OverlappedLabelsMode");if(a!=="hide"&&a!=="rotatethenhide")return 1;var b=this._layoutInfo;a=b.ticks.length;if(a<=2)return 1;var c=this.scale.range().step,d=b.textHeight,e=b.maxTextWidth;if(!(e>0&&d>0&&c>0))return 1;var g=d*this.labelSpacingMin,h=u.Text.measure("x",this.font).width+g,j=b.textAngle,l=this.isAnchorTopOrBottom();b=Math.abs(Math[l?"sin":"cos"](j));j=Math.abs(Math[l?"cos":"sin"](j));d=b<1.0E-8?Infinity:Math.ceil((g+d)/ -(c*b));c=j<1.0E-8?Infinity:Math.ceil((h+e)/(c*j));c=Math.min(d,c);if(!isFinite(c)||c<1||Math.ceil(a/c)<2)c=1;c>1&&i.debug>=3&&this._info("Showing only one in every "+c+" tick labels");return c},_tickMultipliers:[1,2,5,10],_calcNumberVDesiredTickCount:function(){var a=this._layoutInfo,b=a.textHeight*(1+Math.max(0,this.labelSpacingMin));a=a.clientSize[this.anchorLength()];a=Math.max(1,~~(a/b));if(a<=1)return 1;b=this.scale.domain();b=b[1]-b[0];if(b<=0)return a;a=b/a;var c=Math.floor(u.log(a,10));c= -Math.pow(10,c);for(var d,e=this._tickMultipliers,g=0;g=a)break}return Math.max(1,Math.floor(b/d))},_calcNumberHTicks:function(){var a=this._layoutInfo,b=a.clientSize[this.anchorLength()],c=a.textHeight*Math.max(0,this.labelSpacingMin),d=this._calcNumberHDesiredTickCount(c),e=i.debug>=7,g,h,j,l,m;do{e&&this._log("calculateNumberHTicks TickCount IN desired = "+d);j={};this._calcContinuousTicksValue(j,d);var k=j.ticks,n=k.length;if(k.exponentOverflow)if(g==null)if(k.exponent=== -this.exponentMin){l=j;g=1}else{m=j;g=-1}else{if(g===1){if(l)j=l}else if(m)j=m;break}else if(h==null||n!==h){e&&this._log("calculateNumberHTicks TickCount desired/resulting = "+d+" -> "+n);h=n;this._calcContinuousTicksText(j);var o=this._calcNumberHLength(j,c),p=j.excessLength=o-b,q=j.error=Math.abs(p/b);if(e){this._log("calculateNumberHTicks error="+(p>=0?"+":"-")+(j.error*100).toFixed(0)+"% count="+n+" step="+k.step);this._log("calculateNumberHTicks Length client/resulting = "+b+" / "+o+" spacing = "+ -c)}if(p>0){if(d===1){if(n===3&&q<=1){j.ticks.splice(1,1);j.ticksText.splice(1,1);j.ticks.step*=2}else{j.ticks.length=1;j.ticksText.length=1}delete j.maxTextWidth;break}if(l){j=l;break}m=j;g=-1}else{if(q<=0.05||g===-1)break;l=j;g=+1}}d+=g}while(1);if(j){a.ticks=j.ticks;a.ticksText=j.ticksText;a.maxTextWidth=j.maxTextWidth;if(i.debug>=5)this._log("calculateNumberHTicks RESULT error="+(j.excessLength>=0?"+":"-")+(j.error*100).toFixed(0)+"% count="+j.ticks.length+" step="+j.ticks.step)}e&&this._log("calculateNumberHTicks END")}, -_calcNumberHDesiredTickCount:function(a){var b=this._layoutInfo,c=this.scale.domain().map(function(d){d=+d.toFixed(2);d=this.scale.tickFormat(d);return u.Text.measure(d,this.font).width},this);c=Math.max((c[1]+c[0])/2,b.textHeight);b=b.clientSize[this.anchorLength()];return Math.max(1,~~(b/(c+a)))},_calcNumberHLength:function(a,b){a=a.ticksText;var c=f.query(a).select(function(d){return u.Text.measure(d,this.font).width},this).max();return Math.max(c,(a.length-1)*(c+b))},_createCore:function(){if(!this.scale.isNull){var a= -this._layoutInfo.clientSize,b=this._layoutInfo.paddings,c=this.anchorOrtho(),d=this.anchorOpposite(c),e=this.anchorOrthoLength(c),g=this.ruleCrossesMargin?-b[c]:0;this._rSize=a=a[e]+(this.ruleCrossesMargin?b[d]:0)-g;b=this._getRootScene();this.pvRule=(new i.visual.Rule(this,this.pvPanel,{extensionId:"rule"})).lock("data",[b]).override("defaultColor",f.fun.constant("#666666")).lock(this.anchorOpposite(),0).lock(c,g).lock(e,a).pvMark.zOrder(30).strokeDasharray(null).lineCap("square");if(this.isDiscrete)this.useCompositeAxis? -this.renderCompositeOrdinalAxis():this.renderOrdinalAxis();else this.renderLinearAxis()}},_getExtensionId:function(){return""},_getRootScene:function(){if(!this._rootScene){var a=this._rootScene=new i.visual.CartesianAxisRootScene(null,{panel:this,source:this._getRootData()}),b=this._layoutInfo,c=b.ticks,d=b.ticksText;if(this.isDiscrete)if(this.useCompositeAxis)this._buildCompositeScene(a);else{var e=this._tickIncludeModulo;b=this.hiddenLabelText;a.vars.tickIncludeModulo=e;a.vars.hiddenLabelText= -b;var g,h,j,l;if(e>2){var m=a.group.owner.keySep;j=function(){var k=g.map(function(o){return o.key}).join(m),n=h.slice(0,10).join(", ")+(h.length>10?", ...":"");(new i.visual.CartesianAxisTickScene(a,{source:g,tick:k,tickRaw:k,tickLabel:n,isHidden:true})).dataIndex=l;g=h=l=null}}c.forEach(function(k,n){var o=n%e!==0;if(o&&e>2){if(l==null)l=n;(g||(g=[])).push(k);(h||(h=[])).push(d[n])}else{g&&j();(new i.visual.CartesianAxisTickScene(a,{source:k,tick:k.value,tickRaw:k.rawValue,tickLabel:d[n],isHidden:o})).dataIndex= -n}});g&&j()}else c.forEach(function(k,n){(new i.visual.CartesianAxisTickScene(a,{tick:k,tickRaw:k,tickLabel:d[n]})).dataIndex=n},this)}return this._rootScene},_buildCompositeScene:function(a){function b(d){var e=d.group;if(c){var g=d.vars.tick;d.nodeValue=d.value=g.rawValue;d.nodeLabel=d.label=g.label}e.childCount()&&e.children().each(function(h){var j=new i.visual.CartesianAxisTickScene(d,{source:h,tick:h.value,tickRaw:h.rawValue,tickLabel:h.label});j.dataIndex=h.childIndex();b(j)})}var c=this.compatVersion()<= -1;a.vars.tick=new I("","");b(a)},_getRootData:function(){var a=this.chart,b=a.data;if(this.isDiscrete&&this.useCompositeAxis){var c=this.anchor;b=a.visualRoles[this.roleName].select(b,{visible:true,reverse:c=="bottom"||c=="left"})}return b},renderOrdinalAxis:function(){var a=this.scale,b=this.hiddenLabelText,c=this._tickIncludeModulo*a.range().step/2,d=this.anchorOpposite(),e=this.anchorLength(),g=this.anchorOrtho(),h=this.anchorOrthoLength(),j=this.pvRule,l=this._getRootScene(),m=this._layoutInfo, -k=this.compatVersion()<=1,n;if(k){var o=function(s){this.value=this.absValue=s.rawValue;this.path=(this.nodeName=""+(this.value||""))?[this.nodeName]:[];this.label=this.absLabel=s.label};o.prototype.toString=function(){return""+this.value};n=function(s){return function(r){var t=Object.create(this);t.index=this.parent.index;return s.call(t,new o(r.vars.tick))}}}l=(new i.visual.Panel(this,this.pvPanel,{extensionId:"ticksPanel"})).lock("data",l.childNodes).lock(d,0).lockMark(g,function(s){return s.isHidden? -a(s.previousSibling.vars.tick.value)+c:a(s.vars.tick.value)}).lock("strokeDasharray",null).lock("strokeStyle",null).lock("fillStyle",null).lock("lineWidth",0).pvMark.zOrder(20);if(k||this.showTicks)this.pvTicks=(new i.visual.Rule(this,l,{extensionId:"ticks",wrapper:n})).lock("data").intercept("visible",function(){return!this.scene.isHidden&&this.delegateExtension(true)}).optional("lineWidth",1).lock(d,0).lock(g,0).lock(e,null).optional(h,this.tickLength*2/3).override("defaultColor",function(){if(k)return u.Color.names.transparent; -return j.scene?j.scene[0].strokeStyle:"#666666"}).pvMark;var p=this.font,q=this._layoutInfo.maxTextWidth;isFinite(q)||(q=0);this.pvLabel=(new i.visual.Label(this,l,{extensionId:"label",showsInteraction:true,noClick:false,noDoubleClick:false,noSelect:false,noTooltip:false,noHover:false,wrapper:n})).intercept("visible",function(s){return!s.isHidden?this.delegateExtension(true):!!s.vars.hiddenLabelText}).intercept("text",function(s){var r;if(s.isHidden)r=b;else{r=this.delegateExtension();if(r===undefined)r= -s.vars.tick.label;if(q&&(!this.showsInteraction()||!this.scene.isActive))r=i.text.trimToWidthB(q,r,p,"..",false)}return r}).pvMark.zOrder(40).lock(d,this.tickLength).lock(g,0).font(p).textStyle("#666666").textAlign(m.textAlign).textBaseline(m.textBaseline);this._debugTicksPanel(l)},_getTooltipFormatter:function(a){if(this.axis.option("TooltipEnabled")){a.gravity=this._calcTipsyGravity();var b=this.axis.option("TooltipFormat");if(b)return function(d){return b.call(d,d.scene)};var c=this.axis.option("TooltipAutoContent"); -if(c==="summary")return this._summaryTooltipFormatter;if(c==="value"){a.isLazy=false;return function(d){return d.scene.vars.tick.label}}}},_debugTicksPanel:function(a){if(i.debug>=16){var b=this._layoutInfo,c=b.ticksBBoxes||this._calcTicksLabelBBoxes(b);a.add(u.Panel)[this.anchorOpposite()](this.tickLength)[this.anchorOrtho()](0)[this.anchorLength()](0)[this.anchorOrthoLength()](0).fillStyle(null).strokeStyle(null).lineWidth(0).visible(function(d){return!d.isHidden}).add(u.Line).data(function(d){d= -c[d.dataIndex].source.points();if(d.length>1)d=d.concat(d[0]);return d}).left(function(d){return d.x}).top(function(d){return d.y}).strokeStyle("red").lineWidth(0.5).strokeDasharray("-")}},renderLinearAxis:function(){var a=this.scale,b=this.pvRule,c=this.anchorOpposite(),d=this.anchorLength(),e=this.anchorOrtho(),g=this.anchorOrthoLength(),h=this._getRootScene(),j;if(this.compatVersion()<=1)j=function(n){return function(o){var p=Object.create(this);p.index=this.parent.index;return n.call(p,o.vars.tick.rawValue)}}; -h=(new i.visual.Panel(this,this.pvPanel,{extensionId:"ticksPanel"})).lock("data",h.childNodes).lock(c,0).lockMark(e,function(n){return a(n.vars.tick.value)}).lock("strokeStyle",null).lock("fillStyle",null).lock("lineWidth",0).pvMark.zOrder(20);if(this.showTicks){var l=this.pvTicks=(new i.visual.Rule(this,h,{extensionId:"ticks",wrapper:j})).lock("data").override("defaultColor",function(){return b.scene?b.scene[0].strokeStyle:"#666666"}).lock(c,0).lock(e,0).lock(d,null).optional(g,this.tickLength).pvMark; -if(this.showMinorTicks){var m=this._layoutInfo.ticks,k=m.length;m=k>1?Math.abs(a(m[1])-a(m[0]))/2:0;this.pvMinorTicks=(new i.visual.Rule(this,this.pvTicks,{extensionId:"minorTicks",wrapper:j})).lock("data").intercept("visible",function(){return this.index=j.width())return"right"}return"center"}):h.textAlign(c).textBaseline(function(l){if(this.index===0){l=h.toScreenTransform().transformVPosition(h.top());if(l>=j.height())return"bottom"}else if(this.index===l.parent.childNodes.length- -1){l=h.toScreenTransform().transformVPosition(h.top());if(l<=0)return"top"}return"middle"})},_onV1Click:function(a,b){this.isDiscrete&&this.useCompositeAxis&&b.call(a.pvMark,a.scene,a.event)},_onV1DoubleClick:function(a,b){this.isDiscrete&&this.useCompositeAxis&&b.call(a.pvMark,a.scene,a.event)},_getSelectableMarks:function(){if(this.isDiscrete&&this.isVisible&&this.pvLabel)return this.base()},renderCompositeOrdinalAxis:function(){var a=this.isAnchorTopOrBottom(),b=a?"h":"v",c=2,d=2,e=this.font,g= -u.Text.fontHeight(e)/2,h=this._pvLayout=this.getLayoutSingleCluster();h.node.def("fitInfo",null).height(function(m){var k=i.text.getFitInfo(m.dx,m.dy,m.vars.tick.label,e,g);if(!k.h)if(b==="v"&&k.v)d=Math.min(c,m.depth);else c=Math.min(c,m.depth);this.fitInfo(k);return m.dy});h.node.add(u.Bar).fillStyle("rgba(127,127,127,.001)").strokeStyle(function(m){if(m.maxDepth===1||!m.maxDepth)return null;return"rgba(127,127,127,0.3)"}).lineWidth(function(m){if(m.maxDepth===1||!m.maxDepth)return 0;return 0.5}).text(function(m){return m.vars.tick.label}); -var j=a?"center":this.anchor=="left"?"right":"left",l;if(this.compatVersion()<=1)l=function(m){return function(k){return m.call(this,k)}};this.pvLabel=(new i.visual.Label(this,h.label,{extensionId:"label",noClick:false,noDoubleClick:false,noSelect:false,noTooltip:false,noHover:false,showsInteraction:true,wrapper:l,tooltipArgs:{options:{offset:g*2}}})).pvMark.def("lblDirection","h").textAngle(function(m){if(m.depth>=d&&m.depth=c){m=Math.atan(m.dy/ -m.dx);if(m>1.27){this.lblDirection("v");return-Math.PI/2}if(m>0.3){this.lblDirection("d");return-m}}this.lblDirection("h");return 0}).textMargin(1).textAlign(function(m){return b!="v"||m.depth>=d||m.depth>=c?"center":j}).left(function(m){return b!="v"||m.depth>=d||m.depth>=c?m.x+m.dx/2:j=="right"?m.x+m.dx:m.x}).font(e).textStyle("#666666").text(function(m){var k=m.vars.tick.label,n=this.sign;if(!n.scene.isActive||!n.showsInteraction()){n=this.fitInfo();switch(this.lblDirection()){case "h":if(!n.h)return i.text.trimToWidthB(m.dx, -k,e,"..");break;case "v":if(!n.v)return i.text.trimToWidthB(m.dy,k,e,"..");break;case "d":if(!n.d){m=Math.sqrt(f.sqr(m.dy)+f.sqr(m.dx));return i.text.trimToWidthB(m-g,k,e,"..")}break}}return k})},getLayoutSingleCluster:function(){var a=this._getRootScene(),b=this.anchor,c=a.group.treeHeight,d=this._layoutInfo.axisSize;c++;var e=d/c;e-=c>2?1/12*d:0;c=c/(c-1);var g=i.BasePanel.orthogonalLength[b];e=g=="width"?b==="left"?[-e,0]:[e,0]:b==="top"?[0,-e]:[0,e];this.pvRule.sign.override("defaultColor",f.fun.constant(null)).override("defaultStrokeWidth", -f.fun.constant(0));d=this.pvRule.add(u.Panel)[g](d).strokeStyle(null).lineWidth(0).add(u.Panel)[g](d*c).strokeStyle(null).lineWidth(0);d.transform(u.Transform.identity.translate(e[0],e[1]));return d.add(u.Layout.Cluster.Fill).nodes(a.nodes()).orient(b)},_calcTipsyGravity:function(){switch(this.anchor){case "bottom":return"s";case "top":return"n";case "left":return"w";case "right":return"e"}return"s"}});f.type("pvc.AxisTitlePanel",i.TitlePanelAbstract).init(function(a,b,c,d){this.axis=c;this.base(a, -b,d);this._extensionPrefix=c.extensionPrefixes.map(function(e){return e+"Title"})}).add({_calcLayout:function(a){var b=this.axis.scale;if(!b||b.isNull)return new M(0,0);return this.base(a)},_createCore:function(a){var b=this.axis.scale;if(!(!b||b.isNull))return this.base(a)}});f.type("pvc.PiePanel",i.PlotPanel).init(function(a,b,c,d){var e=c.option("ValuesLabelStyle");this.base(a,b,c,d);this.explodedOffsetRadius=c.option("ExplodedSliceRadius");this.explodedSliceIndex=c.option("ExplodedSliceIndex"); -this.activeOffsetRadius=c.option("ActiveSliceRadius");this.labelStyle=e;if(e==="linked"){this.linkInsetRadius=c.option("LinkInsetRadius");this.linkOutsetRadius=c.option("LinkOutsetRadius");this.linkMargin=c.option("LinkMargin");this.linkHandleWidth=c.option("LinkHandleWidth");this.linkLabelSize=c.option("LinkLabelSize");this.linkLabelSpacingMin=c.option("LinkLabelSpacingMin")}}).add({pvPie:null,pvPieLabel:null,valueRoleName:"value",_getV1Datum:function(a){var b=a.datum;if(b){b=Object.create(b);b.percent= -a.vars.value.percent;b=b}return b},_calcLayout:function(a){function b(t){return f.between(L.resolve(t,g),0,g)}function c(t){return f.between(L.resolve(t,e),0,e)}var d=a.clientSize,e=d.width,g=Math.min(e,d.height)/2;if(!g)return new M(0,0);d=u.vector(d.width/2,d.height/2);var h=this._getConstantExtension("label","font");if(!f.string.is(h))h=this.valuesFont;var j=g;if(this.valuesVisible&&this.labelStyle==="linked"){var l=b(this.linkInsetRadius),m=b(this.linkOutsetRadius),k=c(this.linkMargin),n=c(this.linkLabelSize), -o=f.number.to(this._getConstantExtension("label","textMargin"),3),p=u.Text.fontHeight(h)*2/3,q=this.linkHandleWidth*p;k+=q;var s=this.linkLabelSpacingMin*p,r=Math.max(0,e/2-g);r=Math.max(0,m+k+n-r);r=Math.max(0,m+p,r);if(r>=j){this.valuesVisible=false;i.debug>=2&&this._log("Hiding linked labels due to insufficient space.")}else{j-=r;a.link={insetRadius:l,outsetRadius:m,elbowRadius:j+m,linkMargin:k,handleWidth:q,labelSize:n,maxTextWidth:n-o,labelSpacingMin:s,textMargin:o,lineHeight:p}}}l=b(this.explodedOffsetRadius); -m=0;if(this.hoverable())m=b(this.activeOffsetRadius);k=l+m;j=j-k;if(j<0)return new M(0,0);a.resolvePctRadius=b;a.center=d;a.clientRadius=g;a.normalRadius=j;a.explodedOffsetRadius=l;a.activeOffsetRadius=m;a.maxOffsetRadius=k;a.labelFont=h},_createCore:function(a){var b=this,c=b.chart,d=this._buildScene(),e=a.center,g=a.normalRadius,h,j=["slice"];if(this.compatVersion()<=1){j.push("");h=function(k){return function(n){return k.call(this,n.vars.value.value)}}}this.pvPie=(new i.visual.PieSlice(this,this.pvPanel, -{extensionId:j,center:e,activeOffsetRadius:a.activeOffsetRadius,maxOffsetRadius:a.maxOffsetRadius,resolvePctRadius:a.resolvePctRadius,wrapper:h,tooltipArgs:{options:{useCorners:true,gravity:function(){var k=this.midAngle(),n=Math.cos(k)>=0;k=Math.sin(k)>=0;return n?k?"nw":"sw":k?"ne":"se"}}}})).lock("data",d.childNodes).override("angle",function(){return this.scene.vars.value.angle}).override("defaultOffsetRadius",function(){var k=b.explodedSliceIndex;if(k==null||k==this.pvMark.index)return a.explodedOffsetRadius; -return 0}).lock("outerRadius",function(){return c.animate(0,g)}).localProperty("innerRadiusEx",L.parse).intercept("innerRadius",function(){var k=this.delegateExtension();if(k==null){k=this.pvMark.innerRadiusEx();k=k!=null?L.resolve(k,this.pvMark.outerRadius())||0:0}return k>0?c.animate(0,k):0}).pvMark;if(this.valuesVisible){this.valuesFont=a.labelFont;if(this.labelStyle==="inside")this.pvPieLabel=i.visual.ValueLabel.maybeCreate(this,this.pvPie,{wrapper:h}).intercept("visible",function(k){return k.vars.value.angle>= -0.001&&this.delegateExtension(true)}).override("defaultText",function(){return this.scene.vars.value.sliceLabel}).pvMark.textMargin(10);else if(this.labelStyle==="linked"){var l=a.link;d.layoutLinkLabels(a);this.pvLinkPanel=this.pvPanel.add(u.Panel).data(d.childNodes).localProperty("pieSlice").pieSlice(function(){return b.pvPie.scene[this.index]});this.pvLinkLine=(new i.visual.Line(this,this.pvLinkPanel,{extensionId:"linkLine",freePosition:true,noClick:true,noDoubleClick:true,noSelect:true,noTooltip:true, -noHover:true,showsActivity:false})).lockMark("data",function(k){var n=this.parent.pieSlice(),o=n.startAngle+n.angle/2,p=n.outerRadius-l.insetRadius,q=n.left+p*Math.cos(o);n=n.top+p*Math.sin(o);o=k.childNodes[0];if(!o||!o._isFirstDynamicScene){o=new i.visual.PieLinkLineScene(k,q,n,0);o._isFirstDynamicScene=true}else{o.x=q;o.y=n}return k.childNodes}).override("defaultColor",function(k){return k==="stroke"?"black":this.base(k)}).override("defaultStrokeWidth",f.fun.constant(0.5)).pvMark.lock("visible").lock("top", -function(k){return k.y}).lock("left",function(k){return k.x});this.pvPieLabel=(new i.visual.Label(this,this.pvLinkPanel,{extensionId:"label",noClick:false,noDoubleClick:false,noSelect:false,noHover:false,showsInteraction:true})).lockMark("data",function(k){return k.lineScenes}).intercept("textStyle",function(){this._finished=false;var k=this.delegate();if(k&&!this._finished&&!this.mayShowActive()&&this.mayShowNotAmongSelected())k=this.dimColor(k,"text");return k}).pvMark.lock("visible").left(function(k){return k.vars.link.labelX}).top(function(k){return k.vars.link.labelY+ -(this.index+1)*l.lineHeight}).textAlign(function(k){return k.vars.link.labelAnchor}).textMargin(l.textMargin).textBaseline("bottom").text(function(k){return k.vars.link.labelLines[this.index]});if(i.debug>=20){this.pvPanel.add(u.Panel).zOrder(-10).left(e.x-a.clientRadius).top(e.y-a.clientRadius).width(a.clientRadius*2).height(a.clientRadius*2).strokeStyle("red");this.pvPanel.strokeStyle("green");var m=u.Colors.category10();this.pvLinkLine.segmented(true).strokeStyle(function(){return m(this.index)})}}this.pvPieLabel.font(a.labelFont)}}, -_getExtensionId:function(){var a=[{abs:"content"}];this.chart.parent&&a.push({abs:"smallContent"});return a.concat(this.base())},renderInteractive:function(){this.pvPanel.render()},_buildScene:function(){var a=new i.visual.PieRootScene(this);this.sum=a.vars.sumAbs.value;return a}});f.type("pvc.visual.PieRootScene",i.visual.Scene).init(function(a){function b(n,o){if(o){o=o._datums;if(o.length===1)return o[0].atoms[g].label}return h.format(n)}function c(){var n=this.vars.value;n.angle=this.parent.angleScale(n.value); -var o=Math.abs(n.value)/m;n.percent=new I(o,j(o));n.sliceLabel=this.sliceLabel()}var d=a.visualRoles.category.flatten(a.data,i.data.visibleKeyArgs);this.base(null,{panel:a,source:d});var e=new i.visual.RoleVarHelper(this,a.visualRoles.color,{roleVar:"color"}),g=a.visualRoles[a.valueRoleName].firstDimensionName(),h=d.dimensions(g),j=a.chart.options.percentValueFormat,l=this,m=0,k=f.type(i.visual.PieCategoryScene).init(function(n,o){this.base(l,{source:n});this.vars.category=I.fromComplex(n);m+=Math.abs(o); -this.vars.value=new I(o,b(o,n));e.onNewScene(this,true)});a._extendSceneType("category",k,["sliceLabel","sliceLabelMask"]);d.children().each(function(n){var o=n.dimensions(g).sum(i.data.visibleKeyArgs);o!==0&&new k(n,o)});this.angleScale=u.Scale.linear(0,m).range(0,2*Math.PI).by1(Math.abs);this.vars.sumAbs=new I(m,b(m));this.childNodes.forEach(function(n){c.call(n)})}).add({layoutLinkLabels:function(a){var b=-Math.PI/2,c=[],d=[];this.childNodes.forEach(function(e){b=e.layoutI(a,b);(e.vars.link.dir> -0?d:c).push(e)});this._distributeLabels(-1,c,a);this._distributeLabels(+1,d,a)},_distributeLabels:function(a,b,c){b.sort(function(d,e){return f.compare(d.vars.link.targetY,e.vars.link.targetY)});this._distributeLabelsDownwards(b,c)&&this._distributeLabelsUpwards(b,c)&&this._distributeLabelsEvenly(b,c);b.forEach(function(d){d.layoutII(c)})},_distributeLabelsDownwards:function(a,b){var c=b.link.labelSpacingMin;b=b.clientSize.height;for(var d=false,e=0,g=a.length-1;eh){d=true;j.targetY=h}else j.targetY=l}}return d},_distributeLabelsUpwards:function(a,b){b=b.link.labelSpacingMin;for(var c=false,d=a.length-1;d>0;d--){var e=a[d-1].vars.link,g=a[d].vars.link;if(d===1&&e.labelTop()<0)c=true;var h=g.labelTop()-b;if(e.labelBottom()>h){g=e.labelHeight/2;h=h-g;if(h1)d/=a.length-1;var e=0;a.forEach(function(g){g=g.vars.link;var h=g.labelHeight/2;e+=h;g.targetY=e;e+=h+d});return true}});f.type("pvc.visual.PieLinkLabelVar").add({labelTop:function(){return this.targetY-this.labelHeight/2},labelBottom:function(){return this.targetY+this.labelHeight/2}});f.type("pvc.visual.PieCategoryScene",i.visual.Scene).add({sliceLabelMask:function(){return this.panel().valuesMask},sliceLabel:function(){return this.format(this.sliceLabelMask())}, -layoutI:function(a,b){var c=this.vars.value,d=b+c.angle,e=(b+d)/2;b=this.vars.link=new i.visual.PieLinkLabelVar;var g=a.link;c=i.text.justify(c.sliceLabel,g.maxTextWidth,a.labelFont);var h=c.length;b.labelLines=c;b.labelHeight=h*g.lineHeight;this.lineScenes=f.array.create(h,this);c=Math.cos(e);var j=Math.sin(e);e=(h=c>=0)?1:-1;b.labelAnchor=h?"left":"right";a=a.center;h=g.elbowRadius;j=a.y+h*j;var l=a.x+e*h;g=l+e*g.linkMargin;new i.visual.PieLinkLineScene(this,a.x+h*c,j);new i.visual.PieLinkLineScene(this, -l,j);b.elbowY=j;b.targetY=j+0;b.targetX=g;b.dir=e;return d},layoutII:function(a){var b=this.vars.link,c=b.targetY,d=b.targetX;a=a.link.handleWidth;a>0&&new i.visual.PieLinkLineScene(this,d-b.dir*a,c);new i.visual.PieLinkLineScene(this,d,c);b.labelX=d;b.labelY=c-b.labelHeight/2}});f.type("pvc.visual.PieLinkLineScene",i.visual.Scene).init(function(a,b,c,d){this.base(a,{source:a.group,index:d});this.x=b;this.y=c}).add(u.Vector);f.type("pvc.PieChart",i.BaseChart).add({_animatable:true,pieChartPanel:null, -_getColorRoleSpec:function(){return{isRequired:true,defaultSourceRole:"category",defaultDimension:"color*",requireIsDiscrete:true}},_initVisualRoles:function(){this.base();this._addVisualRole("category",{isRequired:true,defaultDimension:"category*",autoCreateDimension:true});this._addVisualRole("value",{isMeasure:true,isRequired:true,isPercent:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:"value"})},_initPlotsCore:function(){new i.visual.PiePlot(this)}, -_preRenderContent:function(a){this.base();if(this.compatVersion()<=1){var b=i.castNumber(this.options.innerGap)||0.95;b=f.between(b,0.1,1);a.paddings=((1-b)*100/2).toFixed(2)+"%"}else if(a.paddings==null)a.paddings=new L(0.025);this.pieChartPanel=new i.PiePanel(this,this.basePanel,this.plots.pie,f.create(a,{scenes:f.getPath(this.options,"pie.scenes")}))}});f.type("pvc.BarAbstractPanel",i.CategoricalAbstractPanel).add({pvBar:null,pvBarLabel:null,pvCategoryPanel:null,pvSecondLine:null,pvSecondDot:null, -_creating:function(){var a=this.defaultVisibleBulletGroupScene();if(a&&!a.hasRenderer()){var b=a.colorAxis,c=b.option("LegendDrawLine");if(!c||b.option("LegendDrawMarker")){b={drawMarker:true,markerShape:b.option("LegendShape"),drawRule:c,markerPvProto:new O};this.extend(b.markerPvProto,"",{constOnly:true});a.renderer(new i.visual.legend.BulletItemDefaultRenderer(b))}}},_createCore:function(){this.base();var a=this,b=a.chart,c=a.plot,d=!!a.stacked,e=a.isOrientationVertical(),g=a.visibleData({ignoreNulls:false}), -h=a.visualRoles.series.flatten(g);g=a._buildScene(g,h);var j=a.axes.ortho,l=a.axes.base,m=j.scale,k=m(0),n=j.sceneScale({sceneVarName:"value",nullToZero:false});j=l.sceneScale({sceneVarName:"category"});m=c.option("BarSizeRatio");var o=c.option("BarSizeMax"),p=c.option("BarStackedMargin"),q=l.scale.range();l=q.band;q=q.step;var s=e===d;if(d)h=l;else{h=h.childCount();h=h>0?l*m/h:0}if(h>o)h=o;a.barWidth=h;a.barStepWidth=q;var r;if(a.compatVersion()<=1)r=function(t){return function(A){var x=Object.create(this.parent), -v=Object.create(this);v.parent=x;var y=A.parent.childIndex(),z=A.childIndex();if(d){x.index=y;v.index=z}else{x.index=z;v.index=y}return t.call(v,A.vars.value.rawValue)}};a.pvBarPanel=(new i.visual.Panel(a,a.pvPanel,{panelType:u.Layout.Band,extensionId:"panel"})).lock("layers",g.childNodes).lockMark("values",function(t){return t.childNodes}).lockMark("orient",e?"bottom-left":"left-bottom").lockMark("layout",d?"stacked":"grouped").lockMark("verticalMode",a._barVerticalMode()).lockMark("yZero",k).pvMark.band.x(j).w(l).differentialControl(a._barDifferentialControl()).item.order(s? -"reverse":null).h(function(t){t=n(t);return t!=null?b.animate(0,t-k):null}).w(h).horizontalRatio(m).verticalMargin(p).end;this.pvBar=(new i.visual.Bar(a,a.pvBarPanel.item,{extensionId:"",freePosition:true,wrapper:r})).lockDimensions().pvMark.antialias(false);c.option("OverflowMarkersVisible")&&this._addOverflowMarkers(r);if(c=i.visual.ValueLabel.maybeCreate(a,a.pvBar,{wrapper:r}))a.pvBarLabel=c.pvMark.visible(function(){return this.scene.target[this.index][e?"height":"width"]>=4})},_barVerticalMode:function(){return null}, -_barDifferentialControl:function(){return null},_getV1Datum:function(a){var b=a.datum;if(b){b=Object.create(b);b.percent=a.vars.value.percent;b=b}return b},_addOverflowMarkers:function(a){var b=this.axes.ortho;if(b.option("FixedMax")!=null)this.pvOverflowMarker=this._addOverflowMarker(false,b.scale,a);if(b.option("FixedMin")!=null)this.pvUnderflowMarker=this._addOverflowMarker(true,b.scale,a)},_addOverflowMarker:function(a,b,c){var d=this.isOrientationVertical(),e=d?"bottom":"left",g=this.anchorOpposite(e), -h=this.anchorOrthoLength(e),j=this.anchorLength(e),l=this._layoutInfo.paddings,m=a?b.min-l[e]:b.max+l[g];b=a?d?0:Math.PI/2:d?Math.PI:-Math.PI/2;return(new i.visual.Dot(this,this.pvBar.anchor("center"),{noSelect:true,noHover:true,noClick:true,noDoubleClick:true,noTooltip:true,freePosition:true,extensionId:a?"underflowMarker":"overflowMarker",wrapper:c})).intercept("visible",function(k){var n=this.delegateExtension();if(n!==undefined&&!n)return false;k=k.vars.value.value;if(k==null)return false;n=this.pvMark.scene.target[this.index]; -k=n[e]+(k>0?n[h]:0);return a?km}).lock(g,null).lock("shapeSize").pvMark.shape("triangle").shapeRadius(function(){return Math.min(Math.sqrt(10),this.scene.target[this.index][j]/2)}).shapeAngle(b).lineWidth(1.5).strokeStyle("red").fillStyle("white")[e](function(){return m+(a?1:-1)*(this.shapeRadius()+2)})},renderInteractive:function(){this.pvPanel.render()},_buildScene:function(a,b){function c(l){var m=new i.visual.Scene(d,{source:l}),k=l.key;m.vars.series=I.fromComplex(l);j.onNewScene(m,false); -e.forEach(function(n){var o=new i.visual.Scene(m,{source:a._childrenByKey[n.key]._childrenByKey[k]});(o.vars.category=I.fromComplex(n)).group=n;h.onNewScene(o,true);j.onNewScene(o,true)})}var d=new i.visual.Scene(null,{panel:this,source:a}),e=a._children,g=this.visualRoles,h=new i.visual.RoleVarHelper(d,g.value,{roleVar:"value",hasPercentSubVar:this.stacked}),j=new i.visual.RoleVarHelper(d,g.color,{roleVar:"color"});b.children().each(c);return d}});f.type("pvc.BarAbstract",i.CategoricalAbstract).init(function(a){this.base(a); -if(a=this.parent)this._valueRole=a._valueRole}).add({_initVisualRoles:function(){this.base();this._addVisualRole("value",{isMeasure:true,isRequired:true,isPercent:this.options.stacked,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:"value"});this._valueRole=this.visualRoles.value},_getCategoryRoleSpec:function(){var a=this.base();a.requireIsDiscrete=true;return a},_initData:function(){this.base.apply(this,arguments);this._valueDim=this.data.dimensions(this._valueRole.firstDimensionName())}}); -f.type("pvc.BarPanel",i.BarAbstractPanel).add({});f.type("pvc.BarChart",i.BarAbstract).add({_animatable:true,_allowV1SecondAxis:true,_initPlotsCore:function(){var a=this.options,b=(new i.visual.BarPlot(this)).option("Trend");if(a.plot2){a=new i.visual.PointPlot(this,{name:"plot2",fixed:{DataPart:"1"},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:true}});b||(b=a.option("Trend"))}b&&new i.visual.PointPlot(this,{name:"trend",fixed:{DataPart:"trend",TrendType:"none",ColorRole:"series",NullInterpolatioMode:"none"}, -defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:false}})},_hasDataPartRole:function(){return true},_createPlotPanels:function(a,b){var c=this.plots,d=new i.BarPanel(this,a,c.bar,Object.create(b));this.barChartPanel=d;var e=c.plot2;if(e){i.debug>=3&&this._log("Creating Point panel.");e=new i.PointPanel(this,a,e,Object.create(b));d.pvSecondLine=e.pvLine;d.pvSecondDot=e.pvDot;e._applyV1BarSecondExtensions=true}if(c=c.trend){i.debug>=3&&this._log("Creating Trends Point panel.");new i.PointPanel(this, -a,c,Object.create(b))}}});f.type("pvc.NormalizedBarPanel",i.BarAbstractPanel).add({_barVerticalMode:function(){return"expand"}});f.type("pvc.NormalizedBarChart",i.BarAbstract).add({_processOptionsCore:function(a){a.stacked=true;this.base(a)},_getContinuousVisibleExtentConstrained:function(a,b,c){if(a.type==="ortho")return{min:0,max:100,minLocked:true,maxLocked:true};return this.base(a,b,c)},_initPlotsCore:function(){new i.visual.NormalizedBarPlot(this)},_createPlotPanels:function(a,b){this.barChartPanel= -new i.NormalizedBarPanel(this,a,this.plots.bar,Object.create(b))}});f.type("pvc.visual.legend.WaterfallBulletGroupScene",i.visual.legend.BulletGroupScene).init(function(a,b){b=f.set(b,"clickMode","none");this.base(a,b);this.createItem(b)}).add({renderer:function(a){if(a!=null)this._renderer=a;return this._renderer},itemSceneType:function(){return i.visual.legend.WaterfallBulletItemScene}});f.type("pvc.visual.legend.WaterfallBulletItemScene",i.visual.legend.BulletItemScene).init(function(a,b){this.base.apply(this, -arguments);var c=i.visual.Interactive;this._ibits=c.Interactive|c.ShowsInteraction;this.color=f.get(b,"color");this.vars.value=new I(null,f.get(b,"label"))});f.type("pvc.WaterfallPanel",i.BarAbstractPanel).add({pvWaterfallLine:null,ruleData:null,_barDifferentialControl:function(){var a=this.chart._isFalling;return function(b){if(a&&!this.index)return 1;b=b.vars.category.group;if(b._isFlattenGroup&&!b._isDegenerateFlattenGroup)return-2;return a?-1:1}},_creating:function(){var a=this._getLegendBulletRootScene(); -if(a)if((a=a.firstChild)&&!a.hasRenderer()){var b={drawRule:true,drawMarker:false,rulePvProto:new O};this.extend(b.rulePvProto,"line",{constOnly:true});a.renderer(new i.visual.legend.BulletItemDefaultRenderer(b))}},_createCore:function(){this.base();var a=this.chart,b=this.isOrientationVertical(),c=b?"bottom":"left",d=this.anchorOrtho(c),e=this._buildRuleScene(),g=a.axes.ortho.scale,h=g(0),j=a.axes.ortho.sceneScale({sceneVarName:"value"}),l=a.axes.base.sceneScale({sceneVarName:"category"}),m=a.axes.base.scale, -k=this.barWidth/2,n=this.barWidth,o=this.barStepWidth,p=a._isFalling,q=a._waterColor;if(this.plot.option("AreasVisible")){var s=u.Colors.category10(),r=this._buildWaterGroupScene(),t=g.range(),A=0.04*(t[1]-t[0]);this.pvWaterfallGroupPanel=(new i.visual.Panel(this,this.pvPanel,{extensionId:"group"})).lock("data",r.childNodes).pvMark.zOrder(-1).fillStyle(function(){return s(0).alpha(0.15)})[d](function(x){return m(x.vars.category.valueLeft)-o/2})[this.anchorLength(c)](function(x){x=x.vars.category; -return Math.abs(m(x.valueRight)-m(x.valueLeft))+o})[c](function(x){x=g(x.vars.value.valueBottom)-A/2;return a.animate(h,x)})[this.anchorOrthoLength(c)](function(x){x=x.vars.value;x=g(x.valueTop)-g(x.valueBottom)+A;return a.animate(0,x)})}this.pvBar.sign.override("baseColor",function(x){var v=this.base(x);if(x==="fill")if(!this.scene.vars.category.group._isFlattenGroup)return u.color(v).alpha(0.5);return v});this.pvWaterfallLine=(new i.visual.Rule(this,this.pvPanel,{extensionId:"line",noTooltip:false, -noHover:false,noSelect:false,noClick:false,noDoubleClick:false})).lock("data",e.childNodes).optional("visible",function(){return p&&!!this.scene.previousSibling||!p&&!!this.scene.nextSibling}).optional(c,function(){return h+a.animate(0,j(this.scene)-h)}).optional(this.anchorLength(c),o+n).optional(d,p?function(){return l(this.scene)-o-k}:function(){return l(this.scene)-k}).override("defaultColor",function(){return q}).pvMark.antialias(true).lineCap("butt");if(this.plot.option("TotalValuesVisible"))this.pvWaterfallLabel= -(new i.visual.Label(this,this.pvWaterfallLine,{extensionId:"lineLabel"})).intercept("visible",function(x){if(x.vars.category.group._isFlattenGroup)return false;return p||!!x.nextSibling}).pvMark[c](function(x){return h+a.animate(0,j(x)-h)})[this.anchorOrtho(c)](l).textAlign(b?"center":"left").textBaseline(function(x){if(!b)return"middle";x=x.vars.direction;if(x==null)return"bottom";return!p===(x==="up")?"bottom":"top"}).textStyle(u.Color.names.darkgray.darker(2)).textMargin(5).text(function(x){return x.vars.value.label})}, -_buildRuleScene:function(){function a(h){var j=h.group,l=new i.visual.Scene(c,{source:j});(l.vars.category=I.fromComplex(j)).group=j;h=h.offset;l.vars.value=new I(h,this.chart._valueDim.format(h))}function b(h,j){var l=h.vars.value.value;h.vars.direction=!j||d===l?null:e===d0){e=d+e;if(e>a.max)a.max=e}e=-b.max;if(e<0){e=d+e;if(ea.max)a.max=e;else if(e=0)return y>=0?y:v;return 0}),t=s(r),A=this.axes.base.sceneScale({sceneVarName:"category"});f.scope(function(){return l&&l.grouping?l.flatten(a).children(): -f.query([null])}).each(function(v){var y=new i.visual.Scene(h,{source:v||a});y.vars.series=I.fromComplex(v);o.onNewScene(y,false);j.forEach(function(z,w){var B=z;if(v)B=B._childrenByKey[v.key];var H=new i.visual.Scene(y,{source:B});H.dataIndex=w;H.vars.category=I.fromComplex(z);n.onNewScene(H,true);w=H.vars.value;z=w.value;w.accValue=z!=null?z:r;o.onNewScene(H,true);B=B!=null&&B.datums().prop("isInterpolated").any(f.truthy);H.isInterpolated=B;H.isNull=z==null;H.isIntermediate=false},this)},this); -p=h.children().reverse().array();var x;p.forEach(c,this);p.forEach(g,this);return h}});f.type("pvc.PointAbstract",i.CategoricalAbstract).add({_animatable:true,_processOptionsCore:function(a){a.panelSizeRatio=1;this.base(a)},_hasDataPartRole:function(){return true},_initVisualRoles:function(){this.base();this._addVisualRole("value",{isMeasure:true,isRequired:true,isPercent:this.options.stacked,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:"value"})},_initPlotsCore:function(){var a= -this.options,b=this._createPointPlot().option("Trend");if(a.plot2){a=new i.visual.PointPlot(this,{name:"plot2",fixed:{DataPart:"1"},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:true}});b||(b=a.option("Trend"))}b&&new i.visual.PointPlot(this,{name:"trend",fixed:{DataPart:"trend",TrendType:"none",ColorRole:"series",NullInterpolatioMode:"none"},defaults:{ColorAxis:2,LinesVisible:true,DotsVisible:false}})},_bindAxes:function(a){this.base(a);(a=this.axesByType.base)&&a.forEach(function(b){b.scaleType=== -"discrete"||b.option.defaults({Offset:0.01})});(a=this.axesByType.ortho)&&a.forEach(function(b){b.option.defaults({Offset:0.04})})},_createPlotPanels:function(a,b){var c=this.plots;this.scatterChartPanel=new i.PointPanel(this,a,c.point,Object.create(b));var d=c.plot2;if(d){i.debug>=3&&this._log("Creating second Point panel.");new i.PointPanel(this,a,d,Object.create(b))}if(c=c.trend){i.debug>=3&&this._log("Creating Trends Point panel.");new i.PointPanel(this,a,c,Object.create(b))}},defaults:{tooltipOffset:10}}); -f.type("pvc.DotChart",i.PointAbstract).add({_createPointPlot:function(){return new i.visual.PointPlot(this,{fixed:{DotsVisible:true}})}});f.type("pvc.LineChart",i.PointAbstract).add({_createPointPlot:function(){return new i.visual.PointPlot(this,{fixed:{LinesVisible:true}})}});f.type("pvc.AreaChart",i.PointAbstract).add({_createPointPlot:function(){return new i.visual.PointPlot(this,{fixed:{AreasVisible:true}})}});i.mStackedLineChart=f.type("pvc.StackedLineChart",i.PointAbstract).add({_createPointPlot:function(){return new i.visual.PointPlot(this, -{fixed:{LinesVisible:true,Stacked:true}})}});f.type("pvc.StackedDotChart",i.PointAbstract).add({_createPointPlot:function(){return new i.visual.PointPlot(this,{fixed:{DotsVisible:true,Stacked:true}})}});i.mStackedAreaChart=f.type("pvc.StackedAreaChart",i.PointAbstract).add({_createPointPlot:function(){return new i.visual.PointPlot(this,{fixed:{AreasVisible:true,Stacked:true},defaults:{LinesVisible:true}})}});f.type("pvc.HeatGridPanel",i.CategoricalAbstractPanel).init(function(a,b,c,d){this.base(a, -b,c,d);this.axes.size=a._getAxis("size",c.option("SizeAxis")-1);b=this.visualRoles;d=c.option("SizeRole");b.size=a.visualRole(d);this.useShapes=c.option("UseShapes");this.shape=c.option("Shape");this.nullShape=c.option("NullShape")}).add({defaultBorder:1,nullBorder:2,selectedBorder:2,_createCore:function(){var a=this;a.base();var b=a._calcCellSize(),c=a.isOrientationVertical()?"bottom":"left",d=i.BasePanel.relativeAnchor[c],e=i.BasePanel.parallelLength[c],g=i.BasePanel.orthogonalLength[c],h=a.visualRoles.series.flatten(a.data, -{visible:true}),j=a._buildScene(a.visibleData({ignoreNulls:false}),h,b);h=j.isColorBound;var l=j.isSizeBound,m=a._buildSignsWrapper(j),k=a.compatVersion()<=1,n=this.axes.base.scale,o=this.axes.ortho.scale,p=n.range().step,q=o.range().step,s=p/2,r=q/2;c=(new i.visual.Panel(a,a.pvPanel)).pvMark.data(j.childNodes)[c](function(t){return o(t.vars.series.value)-r})[g](q);g=["panel"];k&&g.push("");g={extensionId:g,wrapper:m};a.useShapes||f.copy(g,{noSelect:false,noHover:false,noClick:false,noDoubleClick:false, -freeColor:false,noTooltip:k});a.pvHeatGrid=(new i.visual.Panel(a,c,g)).lock("data",function(t){return t.childNodes}).pvMark.lock(d,function(t){return n(t.vars.category.value)-s}).lock(e,p).antialias(false);a.shapes=a.useShapes?a._createShapesHeatMap(b,m,h,l):a._createNoShapesHeatMap(h);if(a.valuesVisible&&!a.valuesMask)a.valuesMask=a._getDefaultValuesMask(h,l);if(b=i.visual.ValueLabel.maybeCreate(a,a.pvHeatGrid,{wrapper:m}))a.pvHeatGridLabel=b.pvMark},_calcCellSize:function(){var a=this.axes.x.scale, -b=this.axes.y.scale;a=(a.max-a.min)/a.domain().length;b=(b.max-b.min)/b.domain().length;if(!this.isOrientationVertical()){var c=a;a=b;b=c}return{width:a,height:b}},_buildSignsWrapper:function(a){if(this.compatVersion()>1)return null;var b=f.query(a.childNodes).object({name:function(c){return""+c.vars.series.value},value:function(c){return f.query(c.childNodes).object({name:function(d){return""+d.vars.category.value},value:function(d){return(d=d.vars.color)?""+d.value:null}})}});return function(c){return function(d){var e= -b[d.vars.series.value],g=d.vars.category.rawValue,h=Object.create(this.parent),j=Object.create(this);j.parent=h;var l=d.childIndex();d=d.parent.childIndex();h.index=l;j.index=d;return c.call(j,e,g)}}},_getDefaultValuesMask:function(a,b){var c=this.visualRoles;if(a=a?"color":b?"size":null)return"{#"+c[a].firstDimensionName()+"}"},_createNoShapesHeatMap:function(a){var b=this._buildGetBaseFillColor(a);return this.pvHeatGrid.sign.override("defaultColor",function(c){if(c==="stroke")return null;return b.call(this.pvMark, -this.scene)}).override("interactiveColor",function(c,d){var e=this.scene;if(e.isActive)return c.alpha(0.6);if(e.anySelected()&&!e.isSelected())return this.dimColor(c,d);return this.base(c,d)}).override("dimColor",function(c){return i.toGrayScale(c,0.6)}).pvMark.lineWidth(1.5)},_buildGetBaseFillColor:function(a){var b=this.axes.color;return a?b.sceneScale({sceneVarName:"color"}):f.fun.constant(b.option("Unbound"))},_createShapesHeatMap:function(a,b,c,d){var e=this;a=e._calcDotAreaRange(a);d&&e.axes.size.setScaleRange(a); -b={extensionId:"dot",freePosition:true,activeSeriesAware:false,wrapper:b,tooltipArgs:e._buildShapesTooltipArgs(c,d)};e=(new i.visual.DotSizeColor(e,e.pvHeatGrid,b)).override("dimColor",function(g){return i.toGrayScale(g,0.6)}).pvMark.lock("shapeAngle");d||e.sign.override("defaultSize",f.fun.constant(a.max));return e},_calcDotAreaRange:function(a){a=Math.min(a.width,a.height)/2;if(this.shape==="diamond")a/=Math.SQRT2;a-=2;a=f.sqr(a);var b=12,c=a-b;if(c<=1){a=Math.max(a,2);b=1;c=a-b;i.debug>=2&&this._warn("Using rescue mode dot area calculation due to insufficient space.")}return{min:b, -max:a,span:c}},_buildShapesTooltipArgs:function(a,b){var c=this.chart;if(this.compatVersion()<=1&&this.showsTooltip()){var d=c.options,e=d.customTooltip;e||(e=function(j,l,m){if(m!=null&&m[0]!==undefined)return m.join(", ");return m});c=this.visualRoles;var g=c.series.grouping.dimensionNames(),h=c.category.grouping.dimensionNames();return{buildTooltip:d.isMultiValued?function(j){var l=j.scene.group;if(!l)return"";var m=i.data.Complex.values(l,g);l=i.data.Complex.values(l,h);var k=[];j=j.scene.vars; -if(b)k[d.sizeValIdx||0]=j.size.value;if(a)k[d.colorValIdx||0]=j.color.value;return e.call(d,m,l,k)}:function(j){j=j.scene.vars;var l=j[a?"color":"size"];return e.call(d,j.series.rawValue,j.category.rawValue,l?l.value:null)}}}},renderInteractive:function(){this.pvPanel.render()},_buildScene:function(a,b,c){function d(n){var o=new i.visual.Scene(h,{source:n});o.vars.series=I.fromComplex(n);j.forEach(function(p){e.call(g,o,p,n)})}function e(n,o,p){n=new i.visual.Scene(n,{source:a._childrenByKey[o.key]._childrenByKey[p.key]}); -n.vars.category=I.fromComplex(o);m.onNewScene(n,true);k.onNewScene(n,true)}var g=this,h=new i.visual.Scene(null,{panel:g,source:a}),j=a._children,l=g.visualRoles,m=new i.visual.RoleVarHelper(h,l.color,{roleVar:"color"}),k=new i.visual.RoleVarHelper(h,l.size,{roleVar:"size"});h.cellSize=c;b.children().each(d);return h}});f.type("pvc.HeatGridChart",i.CategoricalAbstract).add({_allowColorPerCategory:true,_axisCreateIfUnbound:{color:true},_processOptionsCore:function(a){this.base(a);f.set(a,"orthoAxisOrdinal", -true,"legend",false,"panelSizeRatio",1);a="value";var b="value2";if(this.compatVersion()<=1){switch(this.options.colorValIdx){case 0:a="value";break;case 1:a="value2";break;default:a="value"}switch(this.options.sizeValIdx){case 0:b="value";break;case 1:b="value2";break;default:b="value"}}this._colorDimName=a;this._sizeDimName=b},_getCategoryRoleSpec:function(){var a=this.base();a.requireIsDiscrete=true;return a},_getColorRoleSpec:function(){return{isMeasure:true,requireSingleDimension:true,requireIsDiscrete:false, -valueType:Number,defaultDimension:this._colorDimName}},_initVisualRoles:function(){this.base();this._addVisualRole("size",{isMeasure:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:this._sizeDimName})},_initPlotsCore:function(){new i.visual.HeatGridPlot(this)},_collectPlotAxesDataCells:function(a,b){this.base(a,b);if(a.type==="heatGrid"&&a.option("UseShapes")){var c=this.visualRole(a.option("SizeRole"));if(c.isBound()){b=f.array.lazy(b,"size");f.array.lazy(b, -a.option("SizeAxis")-1).push({plot:a,role:c,dataPartValue:a.option("DataPart")})}}},_setAxesScales:function(a){this.base(a);if(!a||this.parent)(a=this.axes.size)&&a.isBound()&&this._createAxisScale(a)},_createPlotPanels:function(a,b){this.heatGridChartPanel=new i.HeatGridPanel(this,a,this.plots.heatGrid,Object.create(b))},defaults:{colorValIdx:0,sizeValIdx:1,measuresIndexes:[2],axisOffset:0,plotFrameVisible:false,colorNormByCategory:true,numSD:2}});f.type("pvc.MetricXYAbstract",i.CartesianAbstract).add({_processOptionsCore:function(a){this.base(a); -a.panelSizeRatio=1},_initVisualRoles:function(){this.base();this._addVisualRole("x",{isMeasure:true,isRequired:true,requireSingleDimension:true,requireIsDiscrete:false,defaultDimension:"x",dimensionDefaults:{valueType:this.options.timeSeries?Date:Number}});this._addVisualRole("y",{isMeasure:true,isRequired:true,requireSingleDimension:true,requireIsDiscrete:false,defaultDimension:"y",dimensionDefaults:{valueType:Number}})},_generateTrendsDataCellCore:function(a,b,c){function d(o){var p=function(x){return x.atoms[m].value}, -q=function(x){return x.atoms[k].value},s=o.datums().sort(null,p).array(),r=f.create(j,{rows:f.query(s),x:p,y:q}),t=c.model(r);if(t){var A=n.owner.dimensions(l).intern(this.root._firstTrendAtomProto);s.forEach(function(x,v){var y=p(x);if(y){x=t.sample(y,q(x),v);if(x!=null){y=f.set(Object.create(o.atoms),m,y,k,x,l,A);a.push(f.set(new i.data.Datum(n.owner,y),"isVirtual",true,"isTrend",true,"trendType",c.type))}}})}}var e=this._serRole,g=this.visualRoles.x,h=b.role,j=b.trend;this._warnSingleContinuousValueRole(h); -var l=this._dataPartRole.firstDimensionName(),m=g.firstDimensionName(),k=h.firstDimensionName(),n=this.visibleData(b.dataPartValue);f.scope(function(){return e.isBound()?n.children():f.query([n])}).each(d,this)}});f.type("pvc.data.MetricPointChartTranslationOper").add({_meaLayoutRoles:["x","y","color","size"],configureType:function(){var a=[],b=[];this.collectFreeDiscreteAndConstinuousIndexes(b,a);var c,d=[];c=a.length;if(c>0){for(var e=this._meaLayoutRoles.length,g=0;g0){a.length=c;this.defReader({names:d,indexes:a})}}c=b.length;if(c>0){d.length=0;this._getUnboundRoleDefaultDimNames("series",c,d);c=d.length;if(c>0){b.length=c;this.defReader({names:d,indexes:b})}}}});f.type("pvc.MetricPointPanel",i.CartesianAbstractPanel).init(function(a,b,c,d){this.base(a,b,c,d);this.axes.size=a._getAxis("size",(c.option("SizeAxis")||0)-1);b=c.option("SizeRole");this.visualRoles.size=b?a.visualRole(b):null;this.linesVisible=c.option("LinesVisible");this.dotsVisible= -c.option("DotsVisible");if(!this.linesVisible&&!this.dotsVisible){this.linesVisible=true;c.option.specify({LinesVisible:true})}if(!this.offsetPaddings)this.offsetPaddings=new F(0.01)}).add({sizeAxisRatio:0.2,sizeAxisRatioTo:"minWidthHeight",autoPaddingByDotSize:true,_v1DimRoleName:{category:"x",value:"y"},_creating:function(){var a=this.defaultVisibleBulletGroupScene();if(a&&!a.hasRenderer()){var b=a.colorAxis,c=f.nullyTo(b.option("LegendDrawMarker",true),this.dotsVisible),d=f.nullyTo(b.option("LegendDrawLine", -true),this.linesVisible);if(c||d){var e={drawMarker:c,drawRule:d};if(c){e.markerShape=b.option("LegendShape",true)||"circle";e.markerPvProto=(new u.Dot).lineWidth(1.5,i.extensionTag).shapeSize(12,i.extensionTag);this.extend(e.markerPvProto,"dot",{constOnly:true})}if(d){e.rulePvProto=(new u.Line).lineWidth(1.5,i.extensionTag);this.extend(e.rulePvProto,"line",{constOnly:true})}a.renderer(new i.visual.legend.BulletItemDefaultRenderer(e))}}},_getRootScene:function(){return f.lazy(this,"_rootScene",this._buildScene, -this)},_calcLayout:function(a){var b=this._getRootScene();b.isSizeBound&&this.axes.size.setScaleRange(this._calcDotAreaRange(a));this._calcAxesPadding(a,b)},_getDotDiameterRefLength:function(a){var b=a.clientSize,c=a.paddings;switch(this.sizeAxisRatioTo){case "minWidthHeight":return Math.min(b.width+c.width,b.height+c.height);case "width":return b.width+c.width;case "height":return b.height+c.height}i.debug>=2&&this._log(f.format("Invalid option 'sizeAxisRatioTo' value. Assuming 'minWidthHeight'.", -[this.sizeAxisRatioTo]));this.sizeRatioTo="minWidthHeight";return this._getDotDiameterRefLength(a)},_calcDotRadiusRange:function(a){a=this.sizeAxisRatio/2*this._getDotDiameterRefLength(a);return{min:Math.sqrt(12),max:a}},_calcDotAreaRange:function(a){var b=this._calcDotRadiusRange(a);if(this.shape==="diamond"){b.max/=Math.SQRT2;b.min/=Math.SQRT2}a=f.sqr(b.max);b=f.sqr(b.min);var c=a-b;if(c<=1){a=Math.max(a,2);b=1;c=a-b;i.debug>=3&&this._log("Using rescue mode dot area calculation due to insufficient space.")}return{min:b, -max:a,span:c}},_calcAxesPadding:function(a,b){var c;if(this.autoPaddingByDotSize){var d=this.axes,e=a.clientSize,g=a.paddings;c={};d.x.setScaleRange(e.width);d.y.setScaleRange(e.height);var h=d.base.sceneScale({sceneVarName:"x"}),j=d.ortho.sceneScale({sceneVarName:"y"}),l=d.base.scale.max,m=d.ortho.scale.max,k=b.isSizeBound,n=k?this.axes.size.scale:null;if(!n){d=f.number.as(this._getExtension("dot","shapeRadius"),0);if(d<=0){d=f.number.as(this._getExtension("dot","shapeSize"),0);if(d<=0)d=12}else d= -f.sqr(d);n=f.fun.constant(d)}c={};var o;if(this.offsetPaddings){o={};F.names.forEach(function(q){var s=i.BasePanel.orthogonalLength[q];o[q]=(this.offsetPaddings[q]||0)*(e[s]+g[s])},this)}var p=function(q,s){if(o)s+=o[q]||0;if(s<0)s=0;var r=c[q];if(r==null||s>r)c[q]=s};b.children().selectMany(function(q){return q.childNodes}).each(function(q){var s=h(q),r=j(q);q=Math.sqrt(n(k?q.vars.size.value:0));p("left",q-s);p("bottom",q-r);p("right",s+q-l);p("top",r+q-m)})}else c=this._calcRequestPaddings(a);a.requestPaddings= -c},_createCore:function(){var a=this;a.base();var b=a.chart,c=a._getRootScene(),d=a._buildSignsWrapper(),e=a.compatVersion()<=1;this._finalizeScene(c);a.pvPanel.zOrder(1);this.pvScatterPanel=(new i.visual.Panel(a,a.pvPanel,{extensionId:"panel"})).lock("data",c.childNodes).pvMark;b=b.selectableByFocusWindow();var g=c.isColorBound&&this.visualRoles.color.isDiscrete();b=(new i.visual.Line(a,a.pvScatterPanel,{extensionId:"line",wrapper:d,noTooltip:false,noSelect:b,showsSelection:!b})).lockMark("data", -function(h){return h.childNodes}).intercept("visible",function(h){if(!a.linesVisible)return false;var j=this.delegateExtension();if(j==null)j=!h.isNull&&(!c.isSizeBound&&!c.isColorBound||c.isSizeBound&&h.vars.size.value!=null||c.isColorBound&&(g||h.vars.color.value!=null));return j}).override("x",function(){return this.scene.basePosition}).override("y",function(){return this.scene.orthoPosition});a.pvLine=b.pvMark;b=(new i.visual.DotSizeColor(a,a.pvLine,{extensionId:"dot",wrapper:d,activeSeriesAware:a.linesVisible})).override("x", -function(){return this.scene.basePosition}).override("y",function(){return this.scene.orthoPosition}).override("color",function(h){if(!a.dotsVisible&&!this.scene.isActive&&!this.scene.isSingle)return i.invisibleFill;return this.base(h)});if(c.isSizeBound)a.autoPaddingByDotSize&&a.sizeAxisRatioTo==="minWidthHeight"||a.pvPanel.borderPanel.overflow("hidden");else b.override("baseSize",function(){if(!a.dotsVisible)if(this.scene.isSingle){var h=Math.max(a.pvLine.scene[this.pvMark.index].lineWidth,0.2)/ -2;return f.sqr(h)}return this.base()});a.pvDot=b.pvMark;a.pvDot.rubberBandSelectionMode="center";if(i.visual.ValueLabel.isNeeded(a)){b=["label"];e&&b.push("lineLabel");if(d=i.visual.ValueLabel.maybeCreate(a,a.pvDot,{extensionId:b,wrapper:d}))a.pvHeatGridLabel=d.pvMark}},_buildSignsWrapper:function(){if(this.compatVersion()>1)return null;return function(a){return function(b){var c={category:b.vars.x.rawValue,value:b.vars.y.rawValue},d=Object.create(this);d.index=b.dataIndex;return a.call(d,c)}}},renderInteractive:function(){this.pvScatterPanel.render()}, -_buildScene:function(){function a(k){var n=new i.visual.Scene(e,{source:k});n.vars.series=I.fromComplex(k);h.onNewScene(n,false);k.datums().each(function(o,p){var q=o.atoms[l.name];if(q.value!=null){var s=o.atoms[m.name];if(s.value!=null){o=new i.visual.Scene(n,{source:o});o.dataIndex=p;o.vars.x=I.fromAtom(q);o.vars.y=I.fromAtom(s);j.onNewScene(o,true);h.onNewScene(o,true);o.isIntermediate=false}}})}function b(k){for(var n=k.childNodes,o,p=0,q=0,s=n.length;p4&&a.defReader({names:"range",indexes:u.range(4,b)});break}return a},_initPlotsCore:function(){new i.visual.BulletPlot(this)},_preRenderContent:function(a){this.bulletChartPanel=new i.BulletChartPanel(this,this.basePanel,this.plots.bullet,a)},defaults:{compatVersion:1,orientation:"horizontal",bulletSize:30,bulletSpacing:50,bulletMargin:100,bulletTitle:"Title",bulletSubtitle:"",bulletTitlePosition:"left", -tooltipFormat:function(a,b,c){return this.chart.options.valueFormat(c)},crosstabMode:false,seriesInRows:false}});f.type("pvc.BulletChartPanel",i.PlotPanel).add({pvBullets:null,pvBullet:null,data:null,onSelectionChange:null,_createCore:function(a){var b=this.chart,c=b.options,d=this.buildData(),e=c.orientation=="horizontal"?"left":"bottom",g,h,j,l,m,k,n,o;if(c.orientation=="horizontal"){a=a.clientSize.width-this.chart.options.bulletMargin-20;g=0;switch(c.bulletTitlePosition){case "top":k=this.chart.options.bulletMargin; -j=0;h="left";l=-12;o=parseInt(c.titleSize/2,10);break;case "bottom":k=this.chart.options.bulletMargin;j=0;h="left";l=c.bulletSize+32;o=0;break;case "right":k=5;j=a+5;h="left";l=parseInt(c.bulletSize/2,10);o=0;break;case "left":default:k=this.chart.options.bulletMargin;j=0;l=parseInt(c.bulletSize/2,10);h="right";o=0}m="bottom";n=function(){return this.index*(c.bulletSize+c.bulletSpacing)+o}}else{a=a.clientSize.height-this.chart.options.bulletMargin-20;switch(c.bulletTitlePosition){case "top":k=this.chart.options.bulletMargin; -j=0;h="left";l=-20;g=0;n=undefined;break;case "bottom":k=this.chart.options.bulletMargin;j=0;h="left";l=a+20;g=0;n=20;break;case "right":k=5;j=this.chart.options.bulletSize+40;h="left";l=a;g=-Math.PI/2;n=undefined;break;case "left":default:k=this.chart.options.bulletMargin;j=-12;l=this.height-this.chart.options.bulletMargin-20;h="left";g=-Math.PI/2;n=undefined}m="right";k=function(){return c.bulletMargin+this.index*(c.bulletSize+c.bulletSpacing)}}this.pvBullets=this.pvPanel.add(u.Panel).data(d)[i.BasePanel.orthogonalLength[e]](a)[i.BasePanel.parallelLength[e]](this.chart.options.bulletSize).margin(20).left(k).top(n); -this.pvBullet=this.pvBullets.add(u.Layout.Bullet).orient(e).ranges(function(r){return r.ranges}).measures(function(r){return r.measures}).markers(function(r){return r.markers});if(b.clickable()&&this.clickAction){var p=this;this.pvBullet.cursor("pointer").event("click",function(r){return p.clickAction(r.title,r.subtitle,r.measures,u.event)})}this.pvBulletRange=this.pvBullet.range.add(u.Bar);this.pvBulletMeasure=this.pvBullet.measure.add(u.Bar).text(function(r,t){return t.formattedMeasures[this.index]}); -this.pvBulletMarker=this.pvBullet.marker.add(u.Dot).shape("square").fillStyle("white").text(function(r,t){return t.formattedMarkers[this.index]});if(this.showsTooltip()){var q=this;this.pvBulletMeasure.localProperty("tooltip").tooltip(function(r,t){return b.options.tooltipFormat.call(q,t.title,t.subtitle,r)});this.pvBulletMarker.localProperty("tooltip").tooltip(function(r,t){return b.options.tooltipFormat.call(q,t.title,t.subtitle,r)});this.pvBulletMeasure.event("mouseover",u.Behavior.tipsy(this.chart._tooltipOptions)); -this.pvBulletMarker.event("mouseover",u.Behavior.tipsy(this.chart._tooltipOptions))}this.pvBulletRule=this.pvBullet.tick.add(u.Rule);this.pvBulletRuleLabel=this.pvBulletRule.anchor(m).add(u.Label).text(this.pvBullet.x.tickFormat);this.pvBulletTitle=this.pvBullet.anchor(e).add(u.Label).font("bold 12px sans-serif").textAngle(g).left(-10).textAlign(h).textBaseline("bottom").left(j).top(l).text(function(r){return r.formattedTitle});this.pvBulletSubtitle=this.pvBullet.anchor(e).add(u.Label).textStyle("#666").textAngle(g).textAlign(h).textBaseline("top").left(j).top(l).text(function(r){return r.formattedSubtitle}); -var s=typeof c.axisDoubleClickAction=="function"?function(r,t){c.axisDoubleClickAction(r,t)}:null;if(b.doubleClickable()&&s){this.pvBulletTitle.cursor("pointer").events("all").event("dblclick",function(r){s(r,arguments[arguments.length-1])});this.pvBulletSubtitle.cursor("pointer").events("all").event("dblclick",function(r){s(r,arguments[arguments.length-1])})}},applyExtensions:function(){this.base();this.extend(this.pvBullets,"bulletsPanel");this.extend(this.pvBullet,"bulletPanel");this.extend(this.pvBulletRange, -"bulletRange");this.extend(this.pvBulletMeasure,"bulletMeasure");this.extend(this.pvBulletMarker,"bulletMarker");this.extend(this.pvBulletRule,"bulletRule");this.extend(this.pvBulletRuleLabel,"bulletRuleLabel");this.extend(this.pvBulletTitle,"bulletTitle");this.extend(this.pvBulletSubtitle,"bulletSubtitle")},_getExtensionId:function(){return[{abs:"content"}].concat(this.base())},buildData:function(){var a=this.chart,b=a.options,c=a.visualRoles.title.grouping,d=a.visualRoles.subTitle.grouping,e=a.visualRoles.value.grouping, -g=a.visualRoles.marker.grouping,h=a.visualRoles.range.grouping,j={title:b.bulletTitle,formattedTitle:b.bulletTitle,subtitle:b.bulletSubtitle,formattedSubtitle:b.bulletSubtitle,ranges:f.array.to(b.bulletRanges)||[],measures:f.array.to(b.bulletMeasures)||[],markers:f.array.to(b.bulletMarkers)||[]};f.set(j,"formattedRanges",j.ranges.map(String),"formattedMeasures",j.measures.map(String),"formattedMarkers",j.markers.map(String));return!e&&!c&&!g&&!d&&!h?[j]:a.data.datums().select(function(l){var m=Object.create(j), -k;if(e){k=e.view(l);m.measures=k.values();m.formattedMeasures=k.labels()}if(c){k=c.view(l);m.title=k.value;m.formattedTitle=k.label}if(d){k=d.view(l);m.subtitle=k.value;m.formattedSubtitle=k.label}if(g){k=g.view(l);m.markers=k.values();m.formattedMarkers=k.labels()}if(h){k=h.view(l);m.ranges=k.values();m.formattedRanges=k.labels()}return m},this).array()}});f.type("pvc.ParallelCoordinates",i.BaseChart).init(function(a){a=a||{};a.dimensions=a.dimensions||{};if(!a.dimensions.value)a.dimensions.value= -{valueType:null};this.base(a)}).add({parCoordPanel:null,_preRenderContent:function(a){this.parCoordPanel=new i.ParCoordPanel(this,this.basePanel,f.create(a,{topRuleOffset:this.options.topRuleOffset,botRuleOffset:this.options.botRuleOffset,leftRuleOffset:this.options.leftRuleOffset,rightRuleOffset:this.options.rightRuleOffset,sortCategorical:this.options.sortCategorical,mapAllDimensions:this.options.mapAllDimensions,numDigits:this.options.numDigits}))},defaults:f.create(i.BaseChart.prototype.defaults, -{compatVersion:1,topRuleOffset:30,botRuleOffset:30,leftRuleOffset:60,rightRuleOffset:60,sortCategorical:true,mapAllDimensions:true,numDigits:0})});f.type("pvc.ParCoordPanel",i.BasePanel).add({anchor:"fill",pvParCoord:null,dimensions:null,dimensionDescr:null,data:null,retrieveData:function(){var a=this.chart.data,b=this.chart.options.numDigits;this.dimensions=a.getVisibleCategories();var c=a.getValues(),d=a.getVisibleSeriesIndexes(),e=a.getVisibleCategoriesIndexes(),g=a.getCategories(),h=this.chart.options.mapAllDimensions? -e.map(function(x){return isNaN(c[x][0])?{categorical:true,len:0,map:[]}:{categorical:false,len:0,map:[],displayValue:[]}}):e.map(function(x){return isNaN(c[x][0])?{categorical:true,len:0,map:[]}:null}),j=function(x,v){x=h[x];var y=null;if(x.categorical){y=x.map[v];if(y==null){y=x.len;x.len++;x.map[v]=y}}else{var z=v.toFixed(b);y=x.map[z];if(y==null){y=x.len;x.len++;x.map[z]=y;x.displayValue[z]=v}}return y};for(var l in h)if(h.hasOwnProperty(l)&&h[l]&&h[l].categorical)h[l].displayValue=h[l].map;var m; -if(this.chart.options.sortCategorical||this.chart.options.mapAllDimensions)for(a=0;a1?y[1]:"";return v});for(a=0;aq){r=q;q=t}}}else{n=q=s=r=c[k][0];for(l=1;lq){r=q;q=t}}}l=(q-r+(s-n))/2;m.min=n;m.max=q;m.step=l;m.categorical=false;if(h[k]){m.map=h[k].map;m.mapLength=h[k].len;m.categorical=h[k].categorical;if(!m.categorical){m.orgValue= -[];l=h[k].map;for(var A in l)if(l.hasOwnProperty(A))m.orgValue[l[A]]=0+A}}}this.dimensionDescr=function(x,v){for(var y={},z=0;z=A[B].min&&H<=A[B].max})}:function(w){return o.every(function(B){return w[B]>=A[B].min&&w[B]<=A[B].max})};this.pvParCoord=this.pvPanel.add(u.Panel).data(c.data).visible(j).add(u.Line).data(o).left(function(w){return s(w)}).bottom(function(w,B){return r[w](B[w])}).strokeStyle("#ddd").lineWidth(1).antialias(false);this.pvPanel.add(u.Rule).data(o).left(s).top(g).bottom(h).anchor("top").add(u.Label).top(n).font("bold 10px sans-serif").text(function(w){return p[w].name});g=[];for(var v in p)if(p.hasOwnProperty(v)){n= -p[v];if(n.categorical){l=s(n.id)+6;for(var y in n.map)if(n.map.hasOwnProperty(y))g[g.length]={x:l,y:r[n.id](n.map[y])+3,label:y}}}this.pvPanel.add(u.Panel).data(g).add(u.Label).left(function(w){return w.x}).bottom(function(w){return w.y}).text(function(w){return w.label}).textAlign("left");var z=this.pvPanel.add(u.Panel);z.add(u.Panel).data(c.data).visible(j).add(u.Line).data(o).left(function(w){return s(w)}).bottom(function(w,B){return r[w](B[w])}).strokeStyle(function(w,B){w=p[x];return t[x](w.orgValue&& -!w.categorical?w.orgValue[B[x]]:B[x])}).lineWidth(1);c=z.add(u.Panel).data(o.map(function(w){return{y:h,dy:k,dim:w}})).left(function(w){return s(w.dim)-30}).width(60).fillStyle("rgba(0,0,0,.001)").cursor("crosshair").event("mousedown",u.Behavior.select()).event("select",a).event("selectend",b).add(u.Bar).left(25).top(function(w){return w.y}).width(10).height(function(w){return w.dy}).fillStyle(function(w){return w.dim==x?t[w.dim]((A[w.dim].max+A[w.dim].min)/2):"hsla(0,0,50%,.5)"}).strokeStyle("white").cursor("move").event("mousedown", -u.Behavior.drag()).event("dragstart",a).event("drag",a);c.anchor("bottom").add(u.Label).textBaseline("top").text(function(w){return p[w.dim].categorical?"":A[w.dim].min.toFixed(e)+p[w.dim].unit});c.anchor("top").add(u.Label).textBaseline("bottom").text(function(w){return p[w.dim].categorical?"":A[w.dim].max.toFixed(e)+p[w.dim].unit});this.extend(this.pvParCoord,"parCoord");this.extend(this.pvPanel,"chart")}});f.type("pvc.DataTree",i.BaseChart).init(function(a){a=a||{};a.dimensionGroups=a.dimensionGroups|| -{};if(!a.dimensionGroups.value)a.dimensionGroups.value={valueType:null};this.base(a)}).add({structEngine:null,structMetadata:null,structDataset:null,DataTreePanel:null,_getColorRoleSpec:function(){return{isRequired:true,defaultSourceRole:"category",requireIsDiscrete:true}},setStructData:function(a){this.structDataset=a.resultset;this.structDataset.length||this._log("Warning: Structure-dataset is empty");this.structMetadata=a.metadata;this.structMetadata.length||this._log("Warning: Structure-Metadata is empty")}, -_preRenderContent:function(a){var b=this.structEngine,c=b?b.type:new i.data.ComplexType;c.addDimension("value",{});var d=new i.data.CrosstabTranslationOper(c,this.structDataset,this.structMetadata,{seriesInRows:true,crosstabMode:true});d.configureType();if(!b)b=this.structEngine=new i.data.Data({type:c});b.load(d.execute(b));i.debug>=3&&this._log(this.structEngine.getInfo());this.dataTreePanel=new i.DataTreePanel(this,this.basePanel,f.create(a,{topRuleOffset:this.options.topRuleOffset,botRuleOffset:this.options.botRuleOffset, -leftRuleOffset:this.options.leftRuleOffset,rightRuleOffset:this.options.rightRuleOffset,boxplotColor:this.options.boxplotColor,valueFontsize:this.options.valueFontsize,headerFontsize:this.options.headerFontsize,border:this.options.border,perpConnector:this.options.perpConnector,numDigits:this.options.numDigits,minVerticalSpace:this.options.minVerticalSpace,connectorSpace:this.options.connectorSpace,minAspectRatio:this.options.minAspectRatio}))},defaults:{compatVersion:1,topRuleOffset:30,botRuleOffset:30, -leftRuleOffset:60,rightRuleOffset:60,boxplotColor:"grey",headerFontsize:16,valueFontsize:20,border:2,perpConnector:false,numDigits:0,connectorSpace:0.15,minVerticalSpace:0.05,minAspectRatio:2}});f.type("pvc.DataTreePanel",i.PlotPanel).add({pvDataTree:null,treeElements:null,structMap:null,structArr:null,hRules:null,vRules:null,rules:null,generatePerpConnectors:function(a){this.hRules=[];this.vRules=[];this.rules=[];for(var b in this.structMap){var c=this.structMap[b];if(c.children!=null){var d=+1E4, -e=-10000,g=c.left+c.width;this.hRules.push({left:g,width:a,bottom:c.bottom+c.height/2});g+=a;for(var h in c.children){var j=this.structMap[c.children[h]],l=j.bottom+j.height/2;if(l>e)e=l;if(ld&&this.vRules.push({left:g,bottom:d,height:e-d})}}},generateLineSegment:function(a,b,c,d){var e=[];e.push({x:a,y:b});e.push({x:c,y:d});this.rules.push(e)},generateConnectors:function(a){this.hRules=[];this.vRules=[];if(this.chart.options.perpConnector)this.generatePerpConnectors(a); -else{this.rules=[];for(var b in this.structMap){var c=this.structMap[b];if(c.children!=null){var d,e,g,h=+1E4,j=-10000;for(g in c.children){e=this.structMap[c.children[g]];d=e.bottom+e.height/2;if(d>j)j=d;if(d4;var d;for(d in this.treeElements)this.treeElements[d]=$.trim(this.treeElements[d]);var e=[];e.getElement=function(o){if(e[o]==null)e[o]={min:+1E4,max:-10000};return e[o]};e.addValue=function(o,p){o=e.getElement(o);if(po.max)o.max=p;return o};var g,h,j;for(d in this.treeElements){j=this.treeElements[d];g=j[0];h=g.charCodeAt(0);j=parseInt(j.slice(1),10);e.addValue("__cols",h);e.addValue(g, -j)}g=e.getElement("__cols");var l=this.innerWidth/(g.max-g.min+1),m=l-b.connectorSpace*l;h=m/b.minAspectRatio;var k=g.min;delete e.__cols;for(d in e){g=e[d];if(typeof g!="function"){var n=g.max-g.min+1;g.gridHeight=this.innerHeight/n;g.cellHeight=g.gridHeight*(1-b.minVerticalSpace);if(g.cellHeight>h)g.cellHeight=h;g.relBottom=(g.gridHeight-g.cellHeight)/2;g.numRows=n}}b=new RegExp("[\\s\"']+","g");this.structMap={};for(d in this.treeElements){n={};j=this.treeElements[d];n.box_id=j;this.structMap[j]= -n;g=j[0];h=g.charCodeAt(0);j=parseInt(j.slice(1),10);g=e.getElement(g);n.colIndex=h-k;n.rowIndex=g.numRows-(j-g.min)-1;n.left=this.leftOffs+n.colIndex*l;n.width=m;if(c){n.bottom=a[4][d];n.height=a[5][d]}else{n.bottom=this.botOffs+n.rowIndex*g.gridHeight+g.relBottom;n.height=g.cellHeight}n.label=a[0][d];n.selector=a[1][d];n.aggregation=a[2][d];h=(a[3][d]||"").replace(b," ");n.children=h===" "||h===""?null:h.split(" ")}this.generateConnectors((l-m)/2);this.structArr=[];for(d in this.structMap){j=this.structMap[d]; -this.structArr.push(j)}},findDataValue:function(a,b){for(var c=0;ce[0])d.hScale=u.Scale.linear(e[0],e[4]);else{h=true;d.hScale=u.Scale.linear(e[0]-1.0E-10,e[0]+1.0E-10)}d.hScale.range(c.left+g,c.left+c.width-g);g=""+e[2];var j;for(j=0;j0&&typeof window[b]!="undefined"){b=window[b];this.addDataPoint(b)}}},_createCore:function(){var a=this,b=this.chart.options;b.smValueFontsize=Math.round(0.6*b.valueFontsize);b.smValueFont=""+b.smValueFontsize+"px sans-serif";b.valueFont=""+b.valueFontsize+"px sans-serif";var c=b.topRuleOffset, -d=b.botRuleOffset,e=b.leftRuleOffset;this.innerWidth=this.width-e-b.rightRuleOffset;this.innerHeight=this.height-c-d;this.botOffs=d;this.leftOffs=e;this.retrieveStructure();this.retrieveData();var g=b.headerFontsize+3;d=this.rules;for(c=0;c=3&&this._log("Creating Point panel.");(new i.PointPanel(this,a,c,Object.create(b)))._v1DimRoleName.value=c.option("OrthoRole")}}, -defaults:{crosstabMode:false}}).addStatic({measureRolesNames:["median","lowerQuartil","upperQuartil","minimum","maximum"]});f.type("pvc.data.TreemapChartTranslationOper").add({_configureTypeCore:function(){var a=[],b=[],c=[];this.collectFreeDiscreteAndConstinuousIndexes(c,b);c=c.length;b=b.length;c&&this._getUnboundRoleDefaultDimNames("category",c,a);b&&f.query(["size","color"]).take(b).each(function(d){this._getUnboundRoleDefaultDimNames(d,1,a)},this);a.length&&this.defReader({names:a})}});f.type("pvc.TreemapPanel", -i.PlotPanel).init(function(a,b,c,d){this.base(a,b,c,d);this.axes.size=a._getAxis("size",(c.option("SizeAxis")||0)-1);this.visualRoles.size=a.visualRole(c.option("SizeRole"));this.layoutMode=c.option("LayoutMode")}).add({_createCore:function(a){var b=this;a=a.clientSize;var c=b._buildScene();if(c){var d=f.number.to(b._getConstantExtension("leaf","lineWidth"),1),e=d/2,g=b.visualRoles.size.isBound()?b.axes.size.scale.by1(function(k){return k.vars.size.value}):100;a=b.pvTreemapPanel=(new i.visual.Panel(b, -b.pvPanel,{panelType:u.Layout.Treemap,extensionId:"panel"})).pvMark.lock("visible",true).lock("nodes",c.nodes()).lock("left",e).lock("top",e).lock("width",a.width-d).lock("height",a.height-d).lock("size",g).lock("mode",b.layoutMode).lock("order",null).lock("round",false);a.node.left(function(k){return k.x+e}).top(function(k){return k.y+e}).width(function(k){return k.dx-d}).height(function(k){return k.dy-d});c=b.axes.color;var h,j;if(b.visualRoles.color.isBound()){j=h=c.sceneScale({sceneVarName:"color"}); -if(b.plot.option("ColorMode")==="byparent")j=j.by(f.propGet("parent"))}else j=h=f.fun.constant(c.option("Unbound"));var l=(new i.visual.Bar(b,a.leaf,{extensionId:"leaf"})).lockMark("visible").override("defaultColor",function(){return j(this.scene)}).override("defaultStrokeWidth",function(){return d}).pvMark.antialias(false).lineCap("round").strokeDasharray(function(k){return k.vars.size.value<0?"dash":null});(new i.visual.Bar(b,a.node,{extensionId:"ascendant",noHover:true,noSelect:true,noClick:true, -noDoubleClick:true})).intercept("visible",function(k){return!!k.parent&&!!k.firstChild&&this.delegateExtension(true)}).override("anyInteraction",function(){return this.scene.anyInteraction()||this.scene.isActiveDescendantOrSelf()}).override("defaultStrokeWidth",function(){return 1.5*d}).override("interactiveStrokeWidth",function(k){if(this.showsActivity()&&this.scene.isActiveDescendantOrSelf())k=Math.max(1,k)*1.5;return k}).override("defaultColor",function(){return h(this.scene)}).override("normalColor", -f.fun.constant(null)).override("interactiveColor",function(k,n){if(n==="stroke"){if(this.showsActivity()){if(this.scene.isActiveDescendantOrSelf())return u.color(k).brighter(0.5);if(this.scene.anyActive())return null}if(this.showsSelection()&&this.scene.isSelectedDescendantOrSelf())return u.color(k).brighter(0.5)}return null}).pvMark.antialias(false);if(b=i.visual.ValueLabel.maybeCreate(b,a.label,{noAnchor:true})){var m=this.valuesFont;b.override("trimText",function(k){var n=this.scene[this.pvMark.textAngle()? -"dy":"dx"]-2;return i.text.trimToWidthB(n,k,m,"..")}).override("calcBackgroundColor",function(){return l.scene[this.pvMark.index].fillStyle})}}},_getExtensionId:function(){return[{abs:!this.chart.parent?"content":"smallContent"}].concat(this.base())},renderInteractive:function(){this.pvTreemapPanel.render()},_buildScene:function(){var a=this.visibleData({ignoreNulls:false});if(!a.childCount())return null;var b=this.visualRoles;a=new i.visual.Scene(null,{panel:this,source:a});var c=new i.visual.RoleVarHelper(a, -b.size,{roleVar:"size",allowNestedVars:true,hasPercentSubVar:true}),d=b.color&&b.color.grouping,e=function(g){var h=g.group;g.vars.category=I.fromComplex(h);c.onNewScene(g,true);if(d)g.vars.color=new I(h.absKey,h.absLabel);else if(!g.parent)g.vars.color=new I(null,"");h.childCount()&&h.children().each(function(j){j.value!=null&&e(new i.visual.Scene(g,{source:j}))});return g};return e(a)}});f.type("pvc.TreemapChart",i.BaseChart).add({_animatable:false,_axisCreateIfUnbound:{color:true},_getColorRoleSpec:function(){return{defaultSourceRole:"category", -defaultDimension:"color*"}},_initVisualRoles:function(){this.base();this._addVisualRole("category",{isRequired:true,defaultDimension:"category*",autoCreateDimension:true});this._addVisualRole("size",{isMeasure:true,isRequired:false,isPercent:true,requireSingleDimension:true,requireIsDiscrete:false,valueType:Number,defaultDimension:"size"})},_getTranslationClass:function(a){return f.type(this.base(a)).add(i.data.TreemapChartTranslationOper)},_getIsNullDatum:f.fun.constant(),_setAxesScales:function(a){this.base(a); -if(!a||this.parent)if((a=this.axes.size)&&a.isBound()){this._createAxisScale(a);a.setScaleRange({min:100,max:1E3})}},_initPlotsCore:function(){var a=new i.visual.TreemapPlot(this);if(this.options.legend==null)this.options.legend=a.option("ColorMode")==="byparent";a=a.option("RootCategoryLabel");this.visualRoles.category.setRootLabel(a);this.visualRoles.color.setRootLabel(a)},_preRenderContent:function(a){this.base();new i.TreemapPanel(this,this.basePanel,this.plots.treemap,a)},_createVisibleData:function(a, -b){return(a=this.base(a,b))?this.visualRoles.category.select(a,{visible:true}):null},defaults:{legend:null}});return i}(def,pv); diff --git a/pacotes/ccc2/pvc/_namespace.pvc.js b/pacotes/ccc2/pvc/_namespace.pvc.js deleted file mode 100755 index 4b8e0da..0000000 --- a/pacotes/ccc2/pvc/_namespace.pvc.js +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Namespace with protovis chart components. - * @name pvc - * @namespace - */ \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/Atom.js b/pacotes/ccc2/pvc/data/Atom.js deleted file mode 100755 index 4bf3230..0000000 --- a/pacotes/ccc2/pvc/data/Atom.js +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Initializes an atom instance. - * - * @name pvc.data.Atom - * - * @class An atom represents a unit of information. - * - *

- * To create an atom, - * call the corresponding dimension's - * {@link pvc.data.Dimension#intern} method. - * - * Usually this is done by a {@link pvc.data.TranslationOper}. - *

- * - * @property {pvc.data.Dimension} dimension The owner dimension. - * - * @property {number} id - * A unique object identifier. - * - * @property {any} rawValue The raw value from which {@link #value} is derived. - *

- * It is not always defined. - * Values may be the result of - * combining multiple source values. - * - * Values may even be constant - * and, as such, - * not be derived from - * any of the source values. - *

- * - * @property {any} value The typed value of the atom. - * It must be consistent with the corresponding {@link pvc.data.DimensionType#valueType}. - * - * @property {string} label The formatted value. - *

- * Only the null atom can have a empty label. - *

- * - * @property {string} key The value of the atom expressed as a - * string in a way that is unique amongst all atoms of its dimension. - *

- * Only the null atom has a key equal to "". - *

- * @property {string} globalKey A semantic key that is unique across atoms of every dimensions. - * - * @constructor - * @private - * @param {pvc.data.Dimension} dimension The dimension that the atom belongs to. - * @param {any} value The typed value. - * @param {string} label The formatted value. - * @param {any} rawValue The source value. - * @param {string} key The key. - */ -def.type('pvc.data.Atom') -.init( -function(dimension, value, label, rawValue, key) { - this.dimension = dimension; - this.id = (value == null ? -def.nextId() : def.nextId()); // Ensure null sorts first, when sorted by id - this.value = value; - this.label = label; - if(rawValue !== undefined){ - this.rawValue = rawValue; - } - this.key = key; -}) -.add( /** @lends pvc.data.Atom */{ - isVirtual: false, - - rawValue: undefined, - - /** - * Obtains the label of the atom. - */ - toString: function(){ - var label = this.label; - if(label != null){ - return label; - } - - label = this.value; - return label != null ? ("" + label) : ""; - } -}); - - -/** - * Comparer for atom according to their id. - */ -function atom_idComparer(a, b) { - return a.id - b.id; // works for numbers... -} - -/** - * Reverse comparer for atom according to their id. - */ -function atom_idComparerReverse(a, b) { - return b.id - a.id; // works for numbers... -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/Complex.js b/pacotes/ccc2/pvc/data/Complex.js deleted file mode 100755 index 936d8b5..0000000 --- a/pacotes/ccc2/pvc/data/Complex.js +++ /dev/null @@ -1,231 +0,0 @@ -var complex_nextId = 1; - -/** - * Initializes a complex instance. - * - * @name pvc.data.Complex - * - * @class A complex is a set of atoms, - * of distinct dimensions, - * all owned by the same data. - * - * @property {number} id - * A unique object identifier. - * - * @property {number} key - * A semantic identifier. - * - * @property {pvc.data.Data} owner - * The owner data instance. - * - * @property {object} atoms - * A index of {@link pvc.data.Atom} by the name of their dimension type. - * - * @constructor - * @param {pvc.data.Complex} [source] - * A complex that provides for an owner and default base atoms. - * - * @param {map(string any)} [atomsByName] - * A map of atoms or raw values by dimension name. - * - * @param {string[]} [dimNames] The dimension names of atoms in {@link atomsByName}. - * The dimension names in this list will be used to build - * the key and label of the complex. - * When unspecified, all the dimensions of the associated complex type - * will be used to create the key and label. - * Null atoms are not included in the label. - * - * @param {object} [atomsBase] - * An object to serve as prototype to the {@link #atoms} object. - *

- * Atoms already present in this object are not set locally. - * The key and default label of a complex only contain information - * from its own atoms. - *

- *

- * The default value is the {@link #atoms} of the argument {@link source}, - * when specified. - *

- */ -def -.type('pvc.data.Complex') -.init(function(source, atomsByName, dimNames, atomsBase, wantLabel, calculate) { - /*jshint expr:true */ - - /* NOTE: this function is a hot spot and as such is performance critical */ - - this.id = complex_nextId++; - - var owner; - if(source){ - owner = source.owner; - if(!atomsBase){ - atomsBase = source.atoms; - } - } - - this.owner = owner || this; - this.atoms = atomsBase ? Object.create(atomsBase) : {}; - - var hadDimNames = !!dimNames; - if(!dimNames){ - dimNames = owner.type._dimsNames; - } - - var atomsMap = this.atoms; - var D = dimNames.length; - var i, dimName; - - if(atomsByName){ - /* Fill the atoms map */ - var ownerDims = owner._dimensions; - - var addAtom = function(dimName, value){ - if(value != null){ // nulls are already in base proto object - var dimension = def.getOwn(ownerDims, dimName); - var atom = dimension.intern(value); - if(!atomsBase || atom !== atomsBase[dimName]) { // don't add atoms already in base proto object - atomsMap[dimName] = atom; - } - } - }; - - if(!hadDimNames){ - for(dimName in atomsByName){ - addAtom(dimName, atomsByName[dimName]); - } - } else { - for(i = 0 ; i < D ; i++){ - dimName = dimNames[i]; - addAtom(dimName, atomsByName[dimName]); - } - } - - if(calculate){ - var newAtomsByName = owner.type._calculate(this); // may be null - for(dimName in newAtomsByName){ - if(!def.hasOwnProp.call(atomsMap, dimName)){ // not yet added - addAtom(dimName, newAtomsByName[dimName]); - } - } - } - } - - /* Build Key and Label */ - if(!D){ - this.value = null; - this.key = ''; - if(wantLabel){ - this.label = ""; - } - } else if(D === 1){ - var singleAtom = atomsMap[dimNames[0]]; - this.value = singleAtom.value; // always typed when only one - this.rawValue = singleAtom.rawValue; // original - this.key = singleAtom.key; // string - if(wantLabel){ - this.label = singleAtom.label; - } - } else { - var key, label; - var labelSep = owner.labelSep; - var keySep = owner.keySep; - - for(i = 0 ; i < D ; i++){ - dimName = dimNames[i]; - var atom = atomsMap[dimName]; - - // Add to key, null or not - if(!i){ - key = atom.key; - } else { - key += keySep + atom.key; - } - - // Add to label, when non-empty - if(wantLabel){ - var atomLabel = atom.label; - if(atomLabel){ - if(!label){ - label = atomLabel; - } else { - label += labelSep + atomLabel; - } - } - } - } - - this.value = this.rawValue = this.key = key; - if(wantLabel){ - this.label = label; - } - } -}) -.add(/** @lends pvc.data.Complex# */{ - - /** - * The separator used between labels of dimensions of a complex. - * Generally, it is the owner's labelSep that is used. - */ - labelSep: " ~ ", - - keySep: ',', - - label: null, - - rawValue: undefined, - - ensureLabel: function(){ - var label = this.label; - if(label != null){ // TODO: don't think this is being used... - label = ""; - var labelSep = this.owner.labelSep; - def.eachOwn(this.atoms, function(atom){ - var alabel = atom.label; - if(alabel){ - if(label){ - label += labelSep + alabel; - } else { - label = alabel; - } - } - }); - - this.label = label; - } - - return label; - }, - - view: function(dimNames){ - return new pvc.data.ComplexView(this, dimNames); - }, - - toString : function() { - var s = [ '' + this.constructor.typeName ]; - - if (this.index != null) { - s.push("#" + this.index); - } - - this.owner.type.dimensionsNames().forEach(function(name) { - s.push(name + ": " + pvc.stringify(this.atoms[name].value)); - }, this); - - return s.join(" "); - } -}); - -pvc.data.Complex.values = function(complex, dimNames){ - var atoms = complex.atoms; - return dimNames.map(function(dimName){ - return atoms[dimName].value; - }); -}; - -pvc.data.Complex.labels = function(complex, dimNames){ - var atoms = complex.atoms; - return dimNames.map(function(dimName){ - return atoms[dimName].label; - }); -}; \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/ComplexView.js b/pacotes/ccc2/pvc/data/ComplexView.js deleted file mode 100755 index 2c208a5..0000000 --- a/pacotes/ccc2/pvc/data/ComplexView.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Initializes a complex view instance. - * - * @name pvc.data.ComplexView - * - * @class Represents a view of certain dimensions over a given source complex instance. - * @extends pvc.data.Complex - * - * @property {pvc.data.Complex} source The source complex instance. - * @property {string} label The composite label of the own atoms in the view. - * @constructor - * @param {pvc.data.Complex} source The source complex instance. - * @param {string[]} viewDimNames The dimensions that should be revealed by the view. - */ -def.type('pvc.data.ComplexView', pvc.data.Complex) -.init(function(source, viewDimNames){ - - this.source = source; - - this.viewDimNames = viewDimNames; - - /* Collect desired source atoms */ - var sourceAtoms = source.atoms, - ownSourceAtoms = []; - - viewDimNames.forEach(function(dimName){ - if(def.hasOwnProp.call(sourceAtoms, dimName)){ - ownSourceAtoms[dimName] = sourceAtoms[dimName]; - } - }); - - // Call base constructor - this.base(source, ownSourceAtoms, viewDimNames, source.owner.atoms, /* wantLabel */ true); -}) -.add({ - values: function(){ - return pvc.data.Complex.values(this, this.viewDimNames); - }, - labels: function(){ - return pvc.data.Complex.labels(this, this.viewDimNames); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/Data.compat.js b/pacotes/ccc2/pvc/data/Data.compat.js deleted file mode 100755 index fdaaa29..0000000 --- a/pacotes/ccc2/pvc/data/Data.compat.js +++ /dev/null @@ -1,159 +0,0 @@ -pvc.data.Data -.add(/** @lends pvc.data.Data# */{ - /** - * Returns some information on the data points - */ - getInfo: function(){ - - var out = ["DATA SUMMARY", pvc.logSeparator, " Dimension", pvc.logSeparator]; - - def.eachOwn(this.dimensions(), function(dimension, name){ - var count = dimension.count(), - type = dimension.type, - features = []; - - features.push('"' + type.label + '"'); - features.push(type.valueTypeName); - - if(type.isComparable){ features.push("comparable"); } - if(!type.isDiscrete){ features.push("continuous"); } - if(type.isHidden){ features.push("hidden"); } - - out.push( - " " + - name + - " (" + features.join(', ') + ")" + - " (" + count + ")\n\t" + - dimension.atoms().slice(0, 10).map(function(atom){ return atom.label; }).join(", ") + - (count > 10 ? "..." : "")); - }); - - //out.push(pvc.logSeparator); - - return out.join("\n"); - }, - - /** - * Returns the values for the dataset - * BoxPlot, DataTree, ParallelCoordinates - * - * @deprecated - */ - getValues: function(){ - /** - * Values is the inner Vs matrix - * X | S1 | ... | S2 | - * ---------------------- - * C1 | V11 | ... | VN1 | - * . | . . - * CJ | V1J | ... | VNJ | - */ - return pv.range(0, this.getCategoriesSize()) - .map(function(categIndex){ - return this._getValuesForCategoryIndex(categIndex); - }, this); - }, - - /** - * Returns the unique values of a given dimension. - * - * @deprecated - */ - _getDimensionValues: function(name){ - return this.dimensions(name).atoms().map(function(atom){ return atom.value; }); - }, - - /** - * Returns the unique visible values of a given dimension. - * - * @deprecated - */ - _getDimensionVisibleValues: function(name){ - return this.dimensions(name).atoms({visible: true}).map(function(atom){ return atom.value; }); - }, - - /** - * Returns the unique series values. - * @deprecated - */ - getSeries: function(){ - return this._getDimensionValues('series'); - }, - - /** - * Returns an array with the indexes of the visible series values. - * @deprecated - */ - getVisibleSeriesIndexes: function(){ - return this.dimensions('series').indexes({visible: true}); - }, - - /** - * Returns an array with the indexes of the visible category values. - * @deprecated - */ - getVisibleCategoriesIndexes: function(){ - return this.dimensions('category').indexes({visible: true}); - }, - - /** - * Returns an array with the visible series. - * @deprecated - */ - getVisibleSeries: function(){ - return this._getDimensionVisibleValues('series'); - }, - - /** - * Returns the categories on the underlying data - * @deprecated - */ - getCategories: function(){ - return this._getDimensionValues('category'); - }, - - /** - * Returns an array with the visible categories. - * - * @deprecated - */ - getVisibleCategories: function(){ - return this._getDimensionVisibleValues('category'); - }, - - /** - * Returns the values for a given category index - * @deprecated - */ - _getValuesForCategoryIndex: function(categIdx){ - var categAtom = this.dimensions('category').atoms()[categIdx]; - var datumsBySeriesKey = this.datums({category: categAtom}) - .uniqueIndex(function(datum){ return datum.atoms.series.key; }); - - // Sorted series atoms - return this.dimensions('series') - .atoms() - .map(function(atom){ - var datum = def.getOwn(datumsBySeriesKey, atom.key); - return datum ? datum.atoms.value.value : null; - }); - }, - - /** - * Returns how many series we have - * @deprecated - */ - getSeriesSize: function(){ - var dim = this.dimensions('series', {assertExists: false}); - return dim ? dim.count() : 0; - }, - - /** - * Returns how many categories, or data points, we have - * @deprecated - */ - getCategoriesSize: function(){ - var dim = this.dimensions('category', {assertExists: false}); - return dim ? dim.count() : 0; - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/Data.js b/pacotes/ccc2/pvc/data/Data.js deleted file mode 100755 index 79ebedd..0000000 --- a/pacotes/ccc2/pvc/data/Data.js +++ /dev/null @@ -1,576 +0,0 @@ - -/** - * Initializes a data instance. - * - * @name pvc.data.Data - * - * @class A data represents a set of datums of the same complex type {@link #type}. - *

- * A data may have a set of atoms that are shared by all of its datums. - * In that case, the {@link #atoms} property holds those atoms. - *

- *

- * A data has one dimension per dimension type of the complex type {@link #type}. - * Each holds information about the atoms of it's type in this data. - * Dimensions are obtained by calling {@link #dimensions}. - *

- *

- * A data may have child data instances. - *

- * - * @extends pvc.data.Complex - * - * @borrows pv.Dom.Node#visitBefore as #visitBefore - * @borrows pv.Dom.Node#visitAfter as #visitAfter - * - * @borrows pv.Dom.Node#nodes as #nodes - * @borrows pv.Dom.Node#firstChild as #firstChild - * @borrows pv.Dom.Node#lastChild as #lastChild - * @borrows pv.Dom.Node#previousSibling as #previousSibling - * @borrows pv.Dom.Node#nextSibling as #nextSibling - * - * @property {pvc.data.ComplexType} type The type of the datums of this data. - * - * @property {pvc.data.Data} root The root data. - * The {@link #root} of a root data is itself. - * - * @property {pvc.data.Data} parent The parent data. - * A root data has a no parent. - * - * @property {pvc.data.Data} linkParent The link parent data. - * - * @property {Number} depth The depth of the data relative to its root data. - * @property {string} label The composite label of the (common) atoms in the data. - * - * @property {string} absLabel The absolute label of the data; - * a composition of all labels up to the root data. - * - * @property {number} absKey - * The absolute semantic identifier; - * a composition of all keys up to the root data. - * - * @constructor - * @param {object} keyArgs Keyword arguments - * @param {pvc.data.Data} [keyArgs.parent] The parent data. - * @param {pvc.data.Data} [keyArgs.linkParent] The link parent data. - * @param {map(string union(any pvc.data.Atom))} [keyArgs.atoms] The atoms shared by contained datums. - * @param {string[]} [keyArgs.dimNames] The dimension names of atoms in {@link keyArgs.atoms}. - * This argument must be specified whenever {@link keyArgs.atoms} is. - * @param {pvc.data.Datum[]|def.Query} [keyArgs.datums] The contained datums array or enumerable. - * @param {pvc.data.Data} [keyArgs.owner] The owner data. - * The topmost root data is its own owner. - * An intermediate root data must specify its owner data. - * - * @param {pvc.data.ComplexType} [keyArgs.type] The complex type. - * Required when no parent or owner are specified. - * - * @param {number} [index=null] The index at which to insert the child in its parent or linked parent. - */ -def.type('pvc.data.Data', pvc.data.Complex) -.init(function(keyArgs){ - /* NOTE: this function is a hot spot and as such is performance critical */ - - /*jshint expr:true*/ - keyArgs || def.fail.argumentRequired('keyArgs'); - - this._visibleDatums = new def.Map(); - - var owner, - atoms, - atomsBase, - dimNames, - datums, - index, - parent = this.parent = keyArgs.parent || null; - if(parent){ - // Not a root - this.root = parent.root; - this.depth = parent.depth + 1; - this.type = parent.type; - datums = keyArgs.datums || def.fail.argumentRequired('datums'); - - owner = parent.owner; - atoms = keyArgs.atoms || def.fail.argumentRequired('atoms'); - dimNames = keyArgs.dimNames|| def.fail.argumentRequired('dimNames'); - atomsBase = parent.atoms; - } else { - // Root (topmost or not) - this.root = this; - // depth = 0 - - dimNames = []; - - var linkParent = keyArgs.linkParent || null; - if(linkParent){ - // A root that is not topmost - owned, linked - owner = linkParent.owner; - //atoms = pv.values(linkParent.atoms); // is atomsBase, below - - this.type = owner.type; - datums = keyArgs.datums || def.fail.argumentRequired('datums');//linkParent._datums.slice(); - this._leafs = []; - - /* - * Inherit link parent atoms. - */ - atomsBase = linkParent.atoms; - //atoms = null - - index = def.get(keyArgs, 'index', null); - - data_addLinkChild.call(linkParent, this, index); - } else { - // Topmost root - an owner - owner = this; - //atoms = null - atomsBase = {}; - - if(keyArgs.labelSep){ - this.labelSep = keyArgs.labelSep; - } - - this.type = keyArgs.type || def.fail.argumentRequired('type'); - - // Only owner datas cache selected datums - this._selectedDatums = new def.Map(); - } - } - - /*global data_setDatums:true */ - if(datums){ - data_setDatums.call(this, datums); - } - - // Must anticipate setting this (and not wait for the base constructor) - // because otherwise new Dimension( ... ) fails. - this.owner = owner; - - /* Need this because of null interning/un-interning and atoms chaining */ - this._atomsBase = atomsBase; - - this._dimensions = {}; - this.type.dimensionsList().forEach(this._initDimension, this); - - // Call base constructors - this.base(owner, atoms, dimNames, atomsBase, /* wantLabel */ true); - - pv.Dom.Node.call(this, /* nodeValue */null); - delete this.nodeValue; - this._children = this.childNodes; // pv.Dom.Node#childNodes - - // Build absolute label and key - // The absolute key is relative to the root data (not the owner - the topmost root) - if(parent){ - index = def.get(keyArgs, 'index', null); - - data_addChild.call(parent, this, index); - - if(parent.absLabel){ - this.absLabel = def.string.join(owner.labelSep, parent.absLabel, this.label); - } else { - this.absLabel = this.label; - } - - if(parent.absKey){ - this.absKey = def.string.join(",", parent.absKey, this.key); - } else { - this.absKey = this.key; - } - } else { - this.absLabel = this.label; - this.absKey = this.key; - } -}) - -// Mix pv.Dom.Node.prototype -.add(pv.Dom.Node) - -.add(/** @lends pvc.data.Data# */{ - parent: null, - linkParent: null, - - /** - * The dimension instances of this data. - * @type pvc.data.Dimension[] - */ - _dimensions: null, - - /** - * The names of unbound dimensions. - * @type string[] - */ - _freeDimensionNames: null, - - /** - * The child data instances of this data. - * @type pvc.data.Data[] - * @internal - */ - _children: null, - - /** - * The link child data instances of this data. - * @type pvc.data.Data[] - * @internal - */ - _linkChildren: null, - - /** - * The leaf data instances of this data. - * - * @type pvc.data.Data[] - * @internal - */ - _leafs: null, - - /** - * The map of child datas by their key. - * - * @type string - * @internal - */ - _childrenByKey: null, - - /** - * A map of visible datums indexed by id. - * @type def.Map - */ - _visibleDatums: null, - - /** - * A map of selected datums indexed by id. - * @type def.Map - */ - _selectedDatums: null, - - /** - * Cache of link child data by grouping operation key. - * @type object - * @internal - */ - _groupByCache: null, - - /** - * An object with cached results of the {@link #dimensionsSumAbs} method. - * - * @type object - */ - _sumAbsCache: null, - - /** - * The height of the tree of datas headed by a root data. - * Only defined in root datas. - */ - treeHeight: null, - - /** - * The grouping operation object used to create this data. - * Only defined in root datas. - * @type pvc.data.GroupingOper - */ - _groupOper: null, - - /** - * A grouping specification object used to create this data, - * along with {@link #groupLevel}. - * Only defined in datas that have children. - * - * @type pvc.data.GroupingSpec - */ - _groupSpec: null, - - /** - * A grouping level specification object used to create this data, - * along with {@link #groupSpec}. - * Only defined in datas that have children. - * - * @type pvc.data.GroupingLevelSpec - */ - _groupLevel: null, - - /** - * The datums of this data. - * @type pvc.data.Datum[] - * @internal - */ - _datums: null, - - /** - * A map of the datums of this data indexed by id. - * @type object - * @internal - */ - _datumsById: null, - - depth: 0, - label: "", - absLabel: "", - - /** - * Indicates if the object has been disposed. - * - * @type boolean - */ - _disposed: false, - - /** - * Indicates that the data was a parent group - * in the flattening group operation. - * - * @type boolean - */ - _isFlattenGroup: false, - _isDegenerateFlattenGroup: false, - - _initDimension: function(dimType){ - this._dimensions[dimType.name] = - new pvc.data.Dimension(this, dimType); - }, - - /** - * Obtains a dimension given its name. - * - *

- * If no name is specified, - * a map with all dimensions indexed by name is returned. - * Do NOT modify this map. - *

- * - *

- * There is one dimension instance per - * dimension type of the data's complex type. - *

- *

- * If this is not a root data, - * the dimensions will be child dimensions of - * the corresponding parent data's dimensions. - *

- *

- * If this is a root data, - * the dimensions will - * have no parent dimension, but instead, an owner dimension. - *

- * - * @param {string} [name] The dimension name. - * @param {object} [keyArgs] Keyword arguments. - * @param {string} [keyArgs.assertExists=true} Indicates that a missing child should be signaled as an error. - * - * @type pvc.data.Dimension - */ - dimensions: function(name, keyArgs){ - if(name == null) { - return this._dimensions; - } - - var dim = def.getOwn(this._dimensions, name); - if(!dim && def.get(keyArgs, 'assertExists', true)) { - throw def.error.argumentInvalid('name', "Undefined dimension '{0}'.", [name]); - } - - return dim; - }, - - /** - * Obtains an array of the names of dimensions that are not bound in {@link #atoms}. - * @type string[] - */ - freeDimensionNames: function(){ - if(!this._freeDimensionNames) { - var free = this._freeDimensionNames = []; - def.eachOwn(this._dimensions, function(dim, dimName){ - var atom = this.atoms[dimName]; - if(!(atom instanceof pvc.data.Atom) || atom.value == null){ - free.push(dimName); - } - }, this); - } - return this._freeDimensionNames; - }, - - /** - * Indicates if the data is an owner. - * - * @type boolean - */ - isOwner: function(){ - return this.owner === this; - }, - - /** - * Obtains an enumerable of the child data instances of this data. - * - * @type pvc.data.Data | def.Query - */ - children: function(){ - if(!this._children) { - return def.query(); - } - -// @param {object} [keyArgs] Keyword arguments. -// @param {string} [keyArgs.key=null} The key of the desired child. -// @param {string} [keyArgs.assertExists=true} Indicates that a missing child should be signaled as an error. -// var key = def.get(keyArgs, 'key'); -// if(key != null) { -// var child = def.getOwn(this._childrenByKey, key); -// if(!child && def.get(keyArgs, 'assertExists', true)) { -// throw def.error.argumentInvalid("Undefined child data with key '{0}'.", [key]); -// } -// -// return child; -// } - - return def.query(this._children); - }, - - /** - * Obtains the number of children. - * - * @type number - */ - childCount: function(){ - return this._children ? this._children.length : 0; - }, - - /** - * Obtains an enumerable of the leaf data instances of this data. - * - * @type def.Query - */ - leafs: function(){ - return def.query(this._leafs); - }, - - /** - * Obtains the number of contained datums. - * @type number - */ - count: function(){ - return this._datums.length; - }, - - /** - * Obtains the single datum of this data, - * or null, when the data no datums or has more than one. - * - * @type pvc.data.Datum - */ - singleDatum: function(){ - var datums = this._datums; - return datums.length === 1 ? datums[0] : null; - }, - - /** - * Disposes the child datas, the link child datas and the dimensions. - * @type undefined - */ - dispose: function(){ - if(!this._disposed){ - data_disposeChildLists.call(this); - if(this._selectedDatums) { this._selectedDatums.clear(); } - this._visibleDatums.clear(); - - def.eachOwn(this._dimensions, function(dimension){ dimension.dispose(); }); - - // myself - - if(this.parent){ - this.parent.removeChild(this); - this.parent = null; - } - - if(this.linkParent) { - /*global data_removeLinkChild:true */ - data_removeLinkChild.call(this.linkParent, this); - } - - this._disposed = true; - } - }, - - /** - * Disposes the child datas and the link child datas. - * @type undefined - */ - disposeChildren: function(){ - /*global data_disposeChildLists:true */ - data_disposeChildLists.call(this); - } -}); - -/** - * Adds a child data. - * - * @name pvc.data.Data#_addChild - * @function - * @param {pvc.data.Data} child The child data to add. - * @param {number} [index=null] The index at which to insert the child. - * @type undefined - * @private - */ -function data_addChild(child, index){ - // this -> ((pv.Dom.Node#)child).parentNode - // child -> ((pv.Dom.Node#)this).childNodes - // ... - this.insertAt(child, index); - - (this._childrenByKey || (this._childrenByKey = {}))[child.key] = child; -} - -/** - * Adds a link child data. - * - * @name pvc.data.Data#_addLinkChild - * @function - * @param {pvc.data.Data} child The link child data to add. - * @param {number} [index=null] The index at which to insert the child. - * @type undefined - * @private - */ -function data_addLinkChild(linkChild, index){ - /*global data_addColChild:true */ - data_addColChild(this, '_linkChildren', linkChild, 'linkParent', index); -} - -/** - * Removes a link child data. - * - * @name pvc.data.Data#_removeLinkChild - * @function - * @param {pvc.data.Data} child The link child data to remove. - * @type undefined - * @private - */ -function data_removeLinkChild(linkChild){ - /*global data_removeColChild:true */ - data_removeColChild(this, '_linkChildren', linkChild, 'linkParent'); -} - -/** - * Disposes the child datas and the link child datas. - * - * @name pvc.data.Data#_disposeChildLists - * @function - * @type undefined - * @private - */ -function data_disposeChildLists() { - /*global data_disposeChildList:true */ - data_disposeChildList(this._children, 'parent'); - this._childrenByKey = null; - - data_disposeChildList(this._linkChildren, 'linkParent'); - this._groupByCache = null; - - // ~ datums.{isSelected, isVisible, isNull}, children - this._sumAbsCache = null; -} - -/** - * Called to assert that this is an owner data. - * - * @private - */ -function data_assertIsOwner(){ - /*jshint expr:true */ - this.isOwner() || def.fail("Can only be called on the owner data."); -} diff --git a/pacotes/ccc2/pvc/data/Data.operations.js b/pacotes/ccc2/pvc/data/Data.operations.js deleted file mode 100755 index 223ebeb..0000000 --- a/pacotes/ccc2/pvc/data/Data.operations.js +++ /dev/null @@ -1,1055 +0,0 @@ -pvc.data.Data.add(/** @lends pvc.data.Data# */{ - - /** - * Loads or reloads the data with the specified enumerable of atoms. - * - *

- * Can only be called on an owner data. - * Child datas are instead "loaded" on construction, - * with a subset of its parent's datums. - *

- * - *

- * This method was designed to be fed with the output - * of {@link pvc.data.TranslationOper#execute}. - *

- * - * @param {def.Query} atomz An enumerable of {@link map(string union(any || pvc.data.Atom))}. - * @param {object} [keyArgs] Keyword arguments. - * @param {function} [keyArgs.isNull] Predicate that indicates if a datum is considered null. - * @param {function} [keyArgs.where] Filter function that approves or excludes each newly read new datum. - */ - load: function(atomz, keyArgs){ - /*global data_assertIsOwner:true */ - data_assertIsOwner.call(this); - - var whereFun = def.get(keyArgs, 'where'); - var isNullFun = def.get(keyArgs, 'isNull'); - var datums = - def - .query(atomz) - .select(function(atoms){ - var datum = new pvc.data.Datum(this, atoms); - - if(isNullFun && isNullFun(datum)){ - datum.isNull = true; - } - - if(whereFun && !whereFun(datum)) { - return null; - } - - return datum; - }, this) - ; - - data_setDatums.call(this, datums, { doAtomGC: true }); - }, - - clearVirtuals: function(){ - // Recursively clears all virtual datums and atoms - var datums = this._datums; - if(datums){ - this._sumAbsCache = null; - - var visibleDatums = this._visibleDatums; - var selectedDatums = this._selectedDatums; - - var i = 0; - var L = datums.length; - var removed; - while(i < L){ - var datum = datums[i]; - if(datum.isVirtual){ - var id = datum.id; - if(selectedDatums && datum.isSelected) { - selectedDatums.rem(id); - } - - if(datum.isVisible) { - visibleDatums.rem(id); - } - - datums.splice(i, 1); - L--; - removed = true; - } else { - i++; - } - } - - if(removed){ - if(!datums.length && this.parent){ - // "Me is a group" - this.dispose(); - return; - } - - var children = this._children; - if(children){ - i = 0; - L = children.length; - while(i < L){ - var childData = children[i]; - childData.clearVirtuals(); - if(!childData.parent){ - // Child group was empty and removed itself - L--; - } else { - i++; - } - } - } - - if(this._linkChildren){ - this._linkChildren.forEach(function(linkChildData){ - linkChildData.clearVirtuals(); - }); - } - } - } - - def.eachOwn(this._dimensions, function(dim){ - /*global dim_uninternVirtualAtoms:true*/ - dim_uninternVirtualAtoms.call(dim); - }); - }, - - /** - * Adds new datums to the owner data. - * @param {pvc.data.Datum[]|def.Query} datums The datums to add. - */ - add: function(datums){ - /*global data_assertIsOwner:true */ - data_assertIsOwner.call(this); - - /*global data_setDatums:true */ - data_setDatums.call(this, datums, { - isAdditive: true, - doAtomGC: true - }); - }, - - /** - * Groups the datums of this data, possibly filtered, - * according to a grouping specification. - * - *

- * The result of the grouping operation over a set of datums - * is a new linked child data. - * - * It is a root data, - * but shares the same {@link #owner} and {@link #atoms} with this, - * and has the considered datums in {@link #datums}. - * - * The data will contain one child data per distinct atom, - * of the first grouping level dimension, - * found in the datums. - * Each child data will contain the datums sharing that atom. - * - * This logic extends to all following grouping levels. - *

- * - *

- * Datums with null atoms on a grouping level dimension are excluded. - *

- * - * @param {string|string[]|pvc.data.GroupingOperSpec} groupingSpecText A grouping specification string or object. - *
-     * "series1 asc, series2 desc, category"
-     * 
- * - * @param {Object} [keyArgs] Keyword arguments object. - * See additional keyword arguments in {@link pvc.data.GroupingOper} - * - * @see #where - * @see pvc.data.GroupingLevelSpec - * - * @returns {pvc.data.Data} The resulting root data. - */ - groupBy: function(groupingSpecText, keyArgs){ - var groupOper = new pvc.data.GroupingOper(this, groupingSpecText, keyArgs), - cacheKey = groupOper.key, - groupByCache, - data; - - if(cacheKey){ - groupByCache = this._groupByCache; - - // Check cache for a linked data with that key - data = groupByCache && groupByCache[cacheKey]; - } - - if(!data) { - if(pvc.debug >= 7){ - pvc.log("[GroupBy] " + (cacheKey ? ("Cache key not found: '" + cacheKey + "'") : "No Cache key")); - } - - data = groupOper.execute(); - - if(cacheKey){ - (groupByCache || (this._groupByCache = {}))[cacheKey] = data; - } - } else if(pvc.debug >= 7){ - pvc.log("[GroupBy] Cache key hit '" + cacheKey + "'"); - } - - return data; - }, - - flattenBy: function(role, keyArgs){ - var grouping = role.flattenedGrouping(keyArgs) || - def.fail.operationInvalid("Role is unbound."); - - return this.groupBy(grouping, keyArgs); - }, - - /** - * Creates a linked data with the result of filtering - * the datums of this data. - * - *

- * This operation differs from {@link #datums} only in the type of output, - * which is a new linked data, instead of an enumerable of the filtered datums. - * See {@link #datums} for more information on the filtering operation. - *

- * - * @param {object} [whereSpec] A "where" specification. - * @param {object} [keyArgs] Keyword arguments object. - * See {@link #datums} for information on available keyword arguments. - * - * @returns {pvc.data.Data} A linked data containing the filtered datums. - */ - where: function(whereSpec, keyArgs){ - var datums = this.datums(whereSpec, keyArgs); - return new pvc.data.Data({linkParent: this, datums: datums}); - }, - - /** - * Obtains the datums of this data, - * possibly filtered according - * to a specified "where" specification, - * datum selected state and - * filtered atom visible state. - * - * @param {object} [whereSpec] A "where" specification. - * A structure with the following form: - *
-     * // OR of datum filters
-     * whereSpec = [datumFilter1, datumFilter2, ...] | datumFilter;
-     * 
-     * // AND of dimension filters
-     * datumFilter = {
-     *      // OR of dimension values
-     *      dimName1: [value1, value2, ...],
-     *      dimName2: value1,
-     *      ...
-     * }
-     * 
- *

Values of a datum filter can also directly be atoms.

- *

- * An example of a "where" specification: - *

- *
-     * whereSpec = [
-     *     // Datums whose series is 'Europe' or 'Australia', 
-     *     // and whose category is 2001 or 2002 
-     *     {series: ['Europe', 'Australia'], category: [2001, 2002]},
-     *     
-     *     // Union'ed with
-     *     
-     *     // Datums whose series is 'America' 
-     *     {series: 'America'},
-     * ];
-     * 
- * - * @param {object} [keyArgs] Keyword arguments object. - * - * @param {boolean} [keyArgs.isNull=null] - * Only considers datums with the specified isNull attribute. - * - * @param {boolean} [keyArgs.visible=null] - * Only considers datums that have the specified visible state. - * - * @param {boolean} [keyArgs.selected=null] - * Only considers datums that have the specified selected state. - * - * @param {function} [keyArgs.where] A arbitrary datum predicate. - * - * @param {string[]} [keyArgs.orderBySpec] An array of "order by" strings to be applied to each - * datum filter of whereSpec. - *

- * An "order by" string is the same as a grouping specification string, - * although it is used here with a slightly different meaning. - * Here's an example of an "order by" string: - *

-     * "series1 asc, series2 desc, category"
-     * 
- * - *

- * When not specified, altogether or individually, - * these are determined to match the corresponding datum filter of whereSpec. - *

- * - *

- * If a string is specified it is treated as the "order by" string corresponding - * to the first datum filter. - *

- * - * @returns {def.Query} A query object that enumerates the desired {@link pvc.data.Datum}. - */ - datums: function(whereSpec, keyArgs){ - if(!whereSpec){ - if(!keyArgs){ - return def.query(this._datums); - } - - return data_whereState(def.query(this._datums), keyArgs); - } - - whereSpec = data_processWhereSpec.call(this, whereSpec, keyArgs); - - return data_where.call(this, whereSpec, keyArgs); - }, - - /** - * Obtains the first datum that - * satisfies a specified "where" specification. - *

- * If no datum satisfies the filter, null is returned. - *

- * - * @param {object} whereSpec A "where" specification. - * See {@link #datums} to know about this structure. - * - * @param {object} [keyArgs] Keyword arguments object. - * See {@link #datums} for additional available keyword arguments. - * - * @param {boolean} [keyArgs.createNull=false] Indicates if a - * null datum should be returned when no datum is satisfied the specified filter. - *

- * The assumption is that the "where" specification - * contains one datum filter, and in turn, - * that it specifies all the dimensions of this data's complex type. - *

- *

- * The first specified datum filter is used as a source to the datums' atoms. - * Also, it is the first atom of each dimension filter that is used. - *

- * - * @returns {pvc.data.Datum} - * The first datum that satisfies the specified filter, - * a null datum, if keyArgs.createNull is truthy, - * or null. - * - * @see pvc.data.Data#datums - */ - datum: function(whereSpec, keyArgs){ - /*jshint expr:true */ - whereSpec || def.fail.argumentRequired('whereSpec'); - - whereSpec = data_processWhereSpec.call(this, whereSpec, keyArgs); - - var datum = data_where.call(this, whereSpec, keyArgs).first() || null; - if(!datum && def.get(keyArgs, 'createNull') && whereSpec.length) { - - /* Create Null Datum */ - var sourceDatumFilter = whereSpec[0], - atoms = {}; - - for(var dimName in this._dimensions){ - var dimAtoms = sourceDatumFilter[dimName]; - if(dimAtoms) { - atoms[dimName] = dimAtoms[0]; - } - } - - // true => null datum - datum = new pvc.data.Datum(this, atoms, true); - } - - return datum; - }, - - /** - * Obtains the first datum of this data, if any. - * @type {pvc.data.Datum} The first datum or null. - */ - firstDatum: function(){ - return this._datums.length ? this._datums[0] : null; - }, - - /** - * Sums the absolute value - * of the sum of a specified dimension on each child. - * - * @param {string} dimName The name of the dimension to sum on each child data. - * @param {object} [keyArgs] Optional keyword arguments that are - * passed to each dimension's {@link pvc.data.Dimension#sum} method. - * - * @type number - */ - dimensionsSumAbs: function(dimName, keyArgs){ - /*global dim_buildDatumsFilterKey:true */ - var key = dimName + ":" + dim_buildDatumsFilterKey(keyArgs), - sum = def.getOwn(this._sumAbsCache, key); - - if(sum == null) { - sum = this.children() - /* non-degenerate flattened parent groups would account for the same values more than once */ - .where(function(childData){ return !childData._isFlattenGroup || childData._isDegenerateFlattenGroup; }) - .select(function(childData){ - return Math.abs(childData.dimensions(dimName).sum(keyArgs)); - }, this) - .reduce(def.add, 0); - - (this._sumAbsCache || (this._sumAbsCache = {}))[key] = sum; - } - - return sum; - } -}); - - -/** - * Called to add or replace the contained {@link pvc.data.Datum} instances. - * - * When replacing, all child datas and linked child datas are disposed. - * - * When adding, the specified datums will be added recursively - * to this data's parent or linked parent, and its parent, until the owner data is reached. - * When crossing a linked parent, - * the other linked children of that parent - * are given a chance to receive a new datum, - * and it will be added if it satisfies its inclusion criteria. - * - * The datums' atoms must be consistent with the base atoms of this data. - * If this data inherits a non-null atom in a given dimension and: - *
    - *
  • a datum has another non-null atom, an error is thrown.
  • - *
  • a datum has a null atom, an error is thrown. - *
- * - * @name pvc.data.Data#_setDatums - * @function - * @param {pvc.data.Datum[]|def.Query} newDatums An array or enumerable of datums. - * When an array, and in replace mode, - * it is used directly to keep the stored datums and may be modified if necessary. - * - * @param {object} [keyArgs] Keyword arguments. - * - * @param {boolean} [keyArgs.isAdditive=false] Indicates that the specified datums are to be added, - * instead of replace existing datums. - * - * @param {boolean} [keyArgs.doAtomGC=true] Indicates that atom garbage collection should be performed. - * - * @type undefined - * @private - */ -function data_setDatums(newDatums, keyArgs){ - // But may be an empty list - /*jshint expr:true */ - newDatums || def.fail.argumentRequired('newDatums'); - - var doAtomGC = def.get(keyArgs, 'doAtomGC', false); - var isAdditive = def.get(keyArgs, 'isAdditive', false); - - var visibleDatums = this._visibleDatums; - var selectedDatums = this._selectedDatums; - - var newDatumsByKey = {}; - var prevDatumsByKey; - var prevDatums = this._datums; - if(prevDatums){ - // Visit atoms of existing datums - // We cannot simply mark all atoms of every dimension - // cause now, the dimensions may already contain new atoms - // used (or not) by the new datums - var processPrevAtoms = isAdditive && doAtomGC; - - // Index existing datums by (semantic) key - // So that old datums may be preserved - prevDatumsByKey = - def - .query(prevDatums) - .uniqueIndex(function(datum){ - - if(processPrevAtoms){ // isAdditive && doAtomGC - data_processDatumAtoms.call( - this, - datum, - /* intern */ false, - /* markVisited */ true); - } - - return datum.key; - }, this); - - // Clear caches and/or children - if(isAdditive){ - this._sumAbsCache = null; - } else { - /*global data_disposeChildLists:true*/ - data_disposeChildLists.call(this); - if(selectedDatums) { selectedDatums.clear(); } - visibleDatums.clear(); - } - } else { - isAdditive = false; - } - - var datumsById; - if(isAdditive){ - datumsById = this._datumsById; - } else { - datumsById = this._datumsById = {}; - } - - if(def.array.is(newDatums)){ - var i = 0; - var L = newDatums.length; - while(i < L){ - var inDatum = newDatums[i]; - var outDatum = setDatum.call(this, inDatum); - if(!outDatum){ - newDatums.splice(i, 1); - L--; - } else { - if(outDatum !== inDatum){ - newDatums[i] = outDatum; - } - i++; - } - } - } else if(newDatums instanceof def.Query){ - newDatums = - newDatums - .select(setDatum, this) - .where(def.notNully) - .array(); - } else { - throw def.error.argumentInvalid('newDatums', "Argument is of invalid type."); - } - - if(doAtomGC){ - // Atom garbage collection - // Unintern unused atoms - def.eachOwn(this._dimensions, function(dimension){ - /*global dim_uninternUnvisitedAtoms:true*/ - dim_uninternUnvisitedAtoms.call(dimension); - }); - } - - if(isAdditive){ - // newDatums contains really new datums (excluding duplicates) - // These can be further filtered in the grouping operation - - def.array.append(prevDatums, newDatums); - - // II - Distribute added datums by linked children - if(this._linkChildren){ - this._linkChildren.forEach(function(linkChildData){ - data_addDatumsSimple.call(linkChildData, newDatums); - }); - } - } else { - this._datums = newDatums; - } - - function setDatum(newDatum){ - if(!newDatum){ - // Ignore - return; - } - - /* Use already existing same-key datum, if any */ - var key = newDatum.key; - - if(def.hasOwnProp.call(newDatumsByKey, key)){ - // Duplicate in input datums, ignore - return; - } - - if(prevDatumsByKey){ - var prevDatum = def.getOwn(prevDatumsByKey, key); - if(prevDatum){ - // Duplicate with previous datums - if(isAdditive){ - // Ignore - return; - } - - // Prefer to *re-add* the old datum and ignore the new one - // Not new - newDatum = prevDatum; - - // The old datum is going to be kept. - // In the end, it will only contain the datums that were "removed" - //delete prevDatumsByKey[key]; - } - // else newDatum is really new - } - - newDatumsByKey[key] = newDatum; - - var id = newDatum.id; - datumsById[id] = newDatum; - - data_processDatumAtoms.call( - this, - newDatum, - /* intern */ !!this._dimensions, // When creating a linked data, datums are set when dimensions aren't yet created. - /* markVisited */ doAtomGC); - - // TODO: make this lazy? - if(!newDatum.isNull){ - if(selectedDatums && newDatum.isSelected) { - selectedDatums.set(id, newDatum); - } - - if(newDatum.isVisible) { - visibleDatums.set(id, newDatum); - } - } - - return newDatum; - } -} - -/** - * Processes the atoms of this datum. - * If a virtual null atom is found then the null atom of that dimension - * is interned. - * If desired the processed atoms are marked as visited. - * - * @name pvc.data.Datum._processAtoms - * @function - * @param {boolean} [intern=false] If virtual nulls should be detected. - * @param {boolean} [markVisited=false] If the atoms should be marked as visited. - * @type undefined - * @internal - */ -function data_processDatumAtoms(datum, intern, markVisited){ - - var dims = this._dimensions; - if(!dims){ - // data is still initializing and dimensions are not yet created - intern = false; - } - - def.each(datum.atoms, function(atom){ - if(intern){ - // Ensure that the atom exists in the local dimension - - var localDim = def.getOwn(dims, atom.dimension.name) || - def.fail.argumentInvalid("Datum has atoms of foreign dimension."); - - /*global dim_internAtom:true */ - dim_internAtom.call(localDim, atom); - } - - if(markVisited){ - // Mark atom as visited - atom.visited = true; - } - }); -} - -function data_addDatumsSimple(newDatums){ - // But may be an empty list - /*jshint expr:true */ - newDatums || def.fail.argumentRequired('newDatums'); - - var groupOper = this._groupOper; - if(groupOper){ - // This data gets its datums, - // possibly filtered (groupOper calls data_addDatumsLocal). - // Children get their new datums. - // Linked children of children get their new datums. - newDatums = groupOper.executeAdd(this, newDatums); - } else { - data_addDatumsLocal.call(this, newDatums); - } - - // Distribute added datums by linked children - if(this._linkChildren){ - this._linkChildren.forEach(function(linkChildData){ - data_addDatumsSimple.call(linkChildData, newDatums); - }); - } -} - -function data_addDatumsLocal(newDatums){ - var visibleDatums = this._visibleDatums; - var selectedDatums = this._selectedDatums; - - // Clear caches - this._sumAbsCache = null; - - var datumsById = this._datumsById; - var datums = this._datums; - - newDatums.forEach(addDatum, this); - - function addDatum(newDatum){ - var id = newDatum.id; - - datumsById[id] = newDatum; - - data_processDatumAtoms.call( - this, - newDatum, - /* intern */ true, - /* markVisited */ false); - - // TODO: make this lazy? - if(!newDatum.isNull){ - if(selectedDatums && newDatum.isSelected) { - selectedDatums.set(id, newDatum); - } - - if(newDatum.isVisible) { - visibleDatums.set(id, newDatum); - } - } - - datums.push(newDatum); - } -} - -/** - * Processes a given "where" specification. - *

- * Normalizes and validates the specification syntax, - * validates dimension names, - * readily excludes uninterned (unexistent) and duplicate values and - * atoms based on their "visible state". - *

- * - *

- * The returned specification contains dimensions instead of their names - * and atoms, instead of their values. - *

- * - * @name pvc.data.Data#_processWhereSpec - * @function - * - * @param {object} whereSpec A "where" specification to be normalized. - * TODO: A structure with the following form: ... - * - * @return Array A processed "where" of the specification. - * A structure with the following form: - *
- * // OR of processed datum filters
- * whereProcSpec = [datumProcFilter1, datumProcFilter2, ...] | datumFilter;
- * 
- * // AND of processed dimension filters
- * datumProcFilter = {
- *      // OR of dimension atoms
- *      dimName1: [atom1, atom2, ...],
- *      dimName2: atom1,
- *      ...
- * }
- * 
- * - * @private - */ -function data_processWhereSpec(whereSpec){ - var whereProcSpec = []; - - whereSpec = def.array.as(whereSpec); - if(whereSpec){ - whereSpec.forEach(processDatumFilter, this); - } - - return whereProcSpec; - - function processDatumFilter(datumFilter){ - if(datumFilter != null) { - /*jshint expr:true */ - (typeof datumFilter === 'object') || def.fail.invalidArgument('datumFilter'); - - /* Map: {dimName1: atoms1, dimName2: atoms2, ...} */ - var datumProcFilter = {}, - any = false; - for(var dimName in datumFilter) { - var atoms = processDimensionFilter.call(this, dimName, datumFilter[dimName]); - if(atoms) { - any = true; - datumProcFilter[dimName] = atoms; - } - } - - if(any) { - whereProcSpec.push(datumProcFilter); - } - } - } - - function processDimensionFilter(dimName, values){ - // throws if it doesn't exist - var dimension = this.dimensions(dimName), - atoms = def.query(values) - .select(function(value){ return dimension.atom(value); }) // null if it doesn't exist - .where(def.notNully) - .distinct(function(atom){ return atom.key; }) - .array(); - - return atoms.length ? atoms : null; - } -} - -/** - * Filters a datum query according to a specified predicate, - * datum selected and visible state. - * - * @name pvc.data.Data#_whereState - * @function - * - * @param {def.query} q A datum query. - * @param {object} [keyArgs] Keyword arguments object. - * See {@link #groupBy} for additional available keyword arguments. - * - * @returns {def.Query} A query object that enumerates the desired {@link pvc.data.Datum}. - * @private - * @static - */ -function data_whereState(q, keyArgs){ - var selected = def.get(keyArgs, 'selected'), - visible = def.get(keyArgs, 'visible'), - where = def.get(keyArgs, 'where'), - isNull = def.get(keyArgs, 'isNull') - ; - - if(visible != null){ - q = q.where(function(datum){ return datum.isVisible === visible; }); - } - - if(isNull != null){ - q = q.where(function(datum){ return datum.isNull === isNull; }); - } - - if(selected != null){ - q = q.where(function(datum){ return datum.isSelected === selected; }); - } - - if(where){ - q = q.where(where); - } - - return q; -} - -// All the "Filter" and "Spec" words below should be read as if they were prepended by "Proc" -/** - * Obtains the datums of this data filtered according to - * a specified "where" specification, - * and optionally, - * datum selected state and filtered atom visible state. - * - * @name pvc.data.Data#_where - * @function - * - * @param {object} [whereSpec] A processed "where" specification. - * @param {object} [keyArgs] Keyword arguments object. - * See {@link #groupBy} for additional available keyword arguments. - * - * @param {string[]} [keyArgs.orderBySpec] An array of "order by" strings to be applied to each - * datum filter of whereSpec. - * - * @returns {def.Query} A query object that enumerates the desired {@link pvc.data.Datum}. - * @private - */ -function data_where(whereSpec, keyArgs) { - - var orderBys = def.array.as(def.get(keyArgs, 'orderBy')), - datumKeyArgs = def.create(keyArgs || {}, { - orderBy: null - }); - - var query = def.query(whereSpec) - .selectMany(function(datumFilter, index){ - if(orderBys) { - datumKeyArgs.orderBy = orderBys[index]; - } - - return data_whereDatumFilter.call(this, datumFilter, datumKeyArgs); - }, this); - - return query.distinct(function(datum){ return datum.id; }); - - /* - // NOTE: this is the brute force / unguided algorithm - no indexes are used - function whereDatumFilter(datumFilter, index){ - // datumFilter = {dimName1: [atom1, OR atom2, OR ...], AND ...} - - return def.query(this._datums).where(datumPredicate, this); - - function datumPredicate(datum){ - if((selected === null || datum.isSelected === selected) && - (visible === null || datum.isVisible === visible)) { - var atoms = datum.atoms; - for(var dimName in datumFilter) { - if(datumFilter[dimName].indexOf(atoms[dimName]) >= 0) { - return true; - } - } - } - } - } - */ -} - -/** - * Obtains an enumerable of the datums satisfying datumFilter, - * by constructing and traversing indexes. - * - * @name pvc.data.Data#_whereDatumFilter - * @function - * - * @param {string} datumFilter A processed datum filter. - * - * @param {Object} keyArgs Keyword arguments object. - * See {@link #groupBy} for additional available keyword arguments. - * - * @param {string} [keyArgs.orderBy] An "order by" string. - * When not specified, one is determined to match the specified datum filter. - * The "order by" string cannot contain multi-dimension levels (dimension names separated with "|"). - * - * @returns {def.Query} A query object that enumerates the desired {@link pvc.data.Datum}. - * - * @private - */ -function data_whereDatumFilter(datumFilter, keyArgs) { - var groupingSpecText = keyArgs.orderBy; // keyArgs is required - if(!groupingSpecText) { - // Choose the most convenient one. - // A sort on dimension names can yield good cache reuse. - groupingSpecText = Object.keys(datumFilter).sort().join(','); - } else { - if(groupingSpecText.indexOf("|") >= 0) { - throw def.error.argumentInvalid('keyArgs.orderBy', "Multi-dimension order by is not supported."); - } - - // TODO: not validating that groupingSpecText actually contains the same dimensions referred in datumFilter... - } - - /* - // NOTE: - // All the code below is just a stack/state-based translation of - // the following recursive code (so that it can be used lazily with a def.query): - - recursive(rootData, 0); - - function recursive(parentData, h) { - if(h >= H) { - // Leaf - parentData._datums.forEach(fun, ctx); - return; - } - - var dimName = parentData._groupLevelSpec.dimensions[0].name; - datumFilter[dimName].forEach(function(atom){ - var childData = parentData._childrenByKey[atom.globalKey]; - if(childData) { - recursive(childData, h + 1); - } - }, this); - } - */ - - var rootData = this.groupBy(groupingSpecText, keyArgs), - H = rootData.treeHeight; - - var stateStack = []; - - // Ad-hoq query - return def.query(function(/* nextIndex */){ - // Advance to next datum - var state; - - // No current data means starting - if(!this._data) { - this._data = rootData; - this._dimAtomsOrQuery = def.query(datumFilter[rootData._groupLevelSpec.dimensions[0].name]); - - // Are there still any datums of the current data to enumerate? - } else if(this._datumsQuery) { - - // - /*jshint expr:true */ - this._data || def.assert("Must have a current data"); - stateStack.length || def.assert("Must have a parent data"); // cause the root node is "dummy" - !this._dimAtomsOrQuery || def.assert(); - // - - if(this._datumsQuery.next()){ - this.item = this._datumsQuery.item; - return 1; // has next - } - - // No more datums here - // Advance to next leaf data node - this._datumsQuery = null; - - // Pop parent data - state = stateStack.pop(); - this._data = state.data; - this._dimAtomsOrQuery = state.dimAtomsOrQuery; - } - - // - this._dimAtomsOrQuery || def.assert("Invalid programmer"); - this._data || def.assert("Must have a current data"); - // - - // Are there still any OrAtom paths of the current data to traverse? - var depth = stateStack.length; - - // Any more atom paths to traverse, from the current data? - do{ - while(this._dimAtomsOrQuery.next()) { - - var dimAtomOr = this._dimAtomsOrQuery.item, - childData = this._data._childrenByKey[dimAtomOr.key]; - - // Also, advance the test of a leaf child data with no datums, to avoid backtracking - if(childData && (depth < H - 1 || childData._datums.length)) { - - stateStack.push({data: this._data, dimAtomsOrQuery: this._dimAtomsOrQuery}); - - this._data = childData; - - if(depth < H - 1) { - // Keep going up, until a leaf datum is found. Then we stop. - this._dimAtomsOrQuery = def.query(datumFilter[childData._groupLevelSpec.dimensions[0].name]); - depth++; - } else { - // Leaf data! - // Set first datum and leave - this._dimAtomsOrQuery = null; - this._datumsQuery = def.query(childData._datums); - this._datumsQuery.next(); - this.item = this._datumsQuery.item; - return 1; // has next - } - } - } // while(atomsOrQuery) - - // No more OR atoms in this _data - if(!depth){ - return 0; // finished - } - - // Pop parent data - state = stateStack.pop(); - this._data = state.data; - this._dimAtomsOrQuery = state.dimAtomsOrQuery; - depth--; - } while(true); - - // Never executes - return 0; // finished - }); -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/Data.selected.js b/pacotes/ccc2/pvc/data/Data.selected.js deleted file mode 100755 index f8e652c..0000000 --- a/pacotes/ccc2/pvc/data/Data.selected.js +++ /dev/null @@ -1,299 +0,0 @@ -pvc.data.Data.add(/** @lends pvc.data.Data# */{ - /** - * Obtains the number of selected datums. - *

- * This method is only optimized when called on an owner data. - *

- * - * @type Number - */ - selectedCount: function(){ - if(!this.isOwner()){ - return this.datums(null, {selected: true}).count(); - } - - return this._selectedDatums.count; - }, - - /** - * Obtains the selected datums, in an unspecified order. - *

- * If the datums should be sorted, - * they can be sorted by their {@link pvc.data.Datum#id}. - * - * Alternatively, {@link #datums} can be called, - * with the selected keyword argument. - *

- * @type pvc.data.Datum[] - */ - selectedDatums: function(){ - if(!this.isOwner()){ - return this.datums(null, {selected: true}).array(); - } - - return this._selectedDatums.values(); - }, - - /** - * Obtains a map containing the selected datums, indexed by id. - * - * @type def.Map(pvc.data.Datum) - */ - selectedDatumMap: function(){ - if(!this.isOwner()){ - - var datums = this - .datums(null, {selected: true}) - .object({ - name: function(datum){ return datum.id; } - }); - - return new def.Set(datums); - } - - return this._selectedDatums.clone(); - }, - - /** - * Obtains the number of visible datums. - * - * @type Number - */ - visibleCount: function(){ - return this._visibleDatums.count; - }, - - /** - * Replaces currently selected datums with the specified datums. - * - * @param {pvc.data.Datum[]|def.query} [datums] The new datums to be selected. - * @returns {boolean} Returns true if any datum was selected and false otherwise. - */ - replaceSelected: function(datums){ - /*global datum_deselect:true */ - - // materialize, cause we're using it twice - if(!def.array.is(datums)){ - datums = datums.array(); - } - - // Clear all but the ones we'll be selecting. - // This way we can have a correct changed flag. - var alreadySelectedById = - def - .query(datums) - .where(function(datum){ return datum.isSelected; }) - .object({ name: function(datum){ return datum.id; } }); - - var changed = this.owner.clearSelected(function(datum){ - return !def.hasOwn(alreadySelectedById, datum.id); - }); - - changed |= pvc.data.Data.setSelected(datums, true); - - return changed; - }, - - /** - * Clears the selected state of any selected datum. - * - * @param {pvc.data.Datum} [funFilter] Allows excluding atoms from the clear operation. - * @returns {boolean} Returns true if any datum was selected and false otherwise. - */ - clearSelected: function(funFilter){ - /*global datum_deselect:true */ - - if(this.owner !== this){ - return this.owner.clearSelected(funFilter); - } - - if(!this._selectedDatums.count) { - return false; - } - - var changed; - if(funFilter){ - changed = false; - this._selectedDatums - .values() - .filter(funFilter) - .forEach(function(datum){ - changed = true; - datum_deselect.call(datum); - this._selectedDatums.rem(datum.id); - }, this); - } else { - changed = true; - this._selectedDatums.values().forEach(function(datum){ - /*global datum_deselect:true */ - datum_deselect.call(datum); - }); - - this._selectedDatums.clear(); - } - - return changed; - } -}); - -/** - * Called by a datum on its owner data - * when its selected state changes. - * - * @name pvc.data.Data#_onDatumSelectedChanged - * @function - * @param {pvc.data.Datum} datum The datum whose selected state changed. - * @param {boolean} selected The new datum selected state. - * @type undefined - * @internal - */ -function data_onDatumSelectedChanged(datum, selected){ - // - /*jshint expr:true */ - !datum.isNull || def.assert("Null datums do not notify selected changes"); - // - - if(selected){ - this._selectedDatums.set(datum.id, datum); - } else { - this._selectedDatums.rem(datum.id); - } - - this._sumAbsCache = null; -} - -/** - * Called by a datum on its owner data - * when its visible state changes. - * - * @name pvc.data.Data#_onDatumVisibleChanged - * @function - * @param {pvc.data.Datum} datum The datum whose visible state changed. - * @param {boolean} selected The new datum visible state. - * @type undefined - * @internal - */ -function data_onDatumVisibleChanged(datum, visible){ - if(def.hasOwn(this._datumsById, datum.id)) { - - // - /*jshint expr:true */ - !datum.isNull || def.assert("Null datums do not notify visible changes"); - // - - if(visible){ - this._visibleDatums.set(datum.id, datum); - } else { - this._visibleDatums.rem(datum.id); - } - - this._sumAbsCache = null; - - // Notify dimensions - def.eachOwn(this._dimensions, function(dimension){ - /*global dim_onDatumVisibleChanged:true */ - dim_onDatumVisibleChanged.call(dimension, datum, visible); - }); - - // Notify child and link child datas - this._children.forEach(function(data){ - data_onDatumVisibleChanged.call(data, datum, visible); - }); - - if(this._linkChildren) { - this._linkChildren.forEach(function(data){ - data_onDatumVisibleChanged.call(data, datum, visible); - }); - } - } -} - -/** - * Sets the selected state of the given datums - * to the state 'select'. - * - * @param {def.Query} datums An enumerable of {@link pvc.data.Datum} to set. - * @param {boolean} selected The desired selected state. - * - * @returns {boolean} true if at least one datum changed its selected state. - * @static - */ -pvc.data.Data.setSelected = function(datums, selected){ - var anyChanged = false; - - if(datums){ - def.query(datums).each(function(datum){ - if(datum.setSelected(selected)){ - // data_onDatumSelectedChanged has already been called - anyChanged = true; - } - }); - } - - return anyChanged; -}; - -/** - * Pseudo-toggles the selected state of the given datums. - * If all are selected, clears their selected state. - * Otherwise, selects all. - * - * @param {def.Query} datums An enumerable of {@link pvc.data.Datum} to toggle. - * - * @returns {boolean} true if at least one datum changed its selected state. - * @static - */ -pvc.data.Data.toggleSelected = function(datums){ - if(!def.array.isLike(datums)){ - datums = def.query(datums).array(); - } - - // Ensure null datums don't affect the result - var allSelected = def.query(datums).all(function(datum){ return datum.isNull || datum.isSelected; }); - return this.setSelected(datums, !allSelected); -}; - -/** - * Sets the visible state of the given datums - * to the state 'visible'. - * - * @param {def.Query} datums An enumerable of {@link pvc.data.Datum} to set. - * @param {boolean} visible The desired visible state. - * - * @returns {boolean} true if at least one datum changed its visible state. - * @static - */ -pvc.data.Data.setVisible = function(datums, visible){ - var anyChanged = false; - - if(datums){ - def.query(datums).each(function(datum){ - if(datum.setVisible(visible)){ - // data_onDatumVisibleChanged has already been called - anyChanged = true; - } - }); - } - - return anyChanged; -}; - -/** - * Pseudo-toggles the visible state of the given datums. - * If all are visible, hides them. - * Otherwise, shows them all. - * - * @param {def.Query} datums An enumerable of {@link pvc.data.Datum} to toggle. - * - * @returns {boolean} true if at least one datum changed its visible state. - * @static - */ -pvc.data.Data.toggleVisible = function(datums){ - if(!def.array.isLike(datums)){ - datums = def.query(datums).array(); - } - - // Ensure null datums don't affect the result (null datums are always visible) - var allVisible = def.query(datums).all(function(datum){ return datum.isVisible; }); - return pvc.data.Data.setVisible(datums, !allVisible); -}; diff --git a/pacotes/ccc2/pvc/data/DataOper.js b/pacotes/ccc2/pvc/data/DataOper.js deleted file mode 100755 index c3ebd85..0000000 --- a/pacotes/ccc2/pvc/data/DataOper.js +++ /dev/null @@ -1,32 +0,0 @@ - -/** - * Initializes a data operation. - * - * @name pvc.data.DataOper - * - * @class The base abstract class for a data operation. - * Performs an initial query on the datums of the opertion's link parent - * and hands the final implementation to a derived class. - * - * @property {string} key Set on construction with a value that identifies the operation. - * - * @constructor - * - * @param {pvc.data.Data} linkParent The link parent data. - * @param {object} [keyArgs] Keyword arguments. - */ -def.type('pvc.data.DataOper') -.init(function(linkParent, keyArgs){ - this._linkParent = linkParent; -}). -add(/** @lends pvc.data.DataOper */{ - - key: null, - - /** - * Performs the data operation. - * - * @returns {pvc.data.Data} The resulting root data. - */ - execute: def.method({isAbstract: true}) -}); diff --git a/pacotes/ccc2/pvc/data/Datum.js b/pacotes/ccc2/pvc/data/Datum.js deleted file mode 100755 index 9370490..0000000 --- a/pacotes/ccc2/pvc/data/Datum.js +++ /dev/null @@ -1,140 +0,0 @@ - -/** - * Initializes a datum instance. - * - * @name pvc.data.Datum - * - * @class A datum is a complex that contains atoms for all the - * dimensions of the associated {@link #data}. - * - * @extends pvc.data.Complex - * - * @property {boolean} isNull Indicates if the datum is a null datum. - *

- * A null datum is a datum that doesn't exist in the data source, - * but is created for auxiliary reasons (null pattern). - *

- * - * @property {boolean} isSelected The datum's selected state (read-only). - * @property {boolean} isVisible The datum's visible state (read-only). - * - * @constructor - * @param {pvc.data.Data} data The data instance to which the datum belongs. - * Note that the datum will belong instead to the owner of this data. - * However the datums atoms will inherit from the atoms of the specified data. - * This is essentially to facilitate the creation of null datums. - * @param {map(string any)} [atomsByName] A map of atoms or raw values by dimension name. - * @param {boolean} [isNull=false] Indicates if the datum is a null datum. - */ -def.type('pvc.data.Datum', pvc.data.Complex) -.init( -function(data, atomsByName, isNull){ - - this.base(data, atomsByName, /* dimNames */ null, /*atomsBase*/ null, /*wantLabel*/ false, /*calculate*/!isNull); - - if(isNull) { - this.isNull = true; - } // otherwise inherit prototype default value -}) -.add(/** @lends pvc.data.Datum# */{ - - isSelected: false, - isVisible: true, - isNull: false, - - isVirtual: false, // like isNull, but is actually in a Data - - isTrend: false, - trendType: null, - - isInterpolated: false, - //isInterpolatedMiddle: false, - interpolation: null, - - /** - * Sets the selected state of the datum to a specified value. - * - * @param {boolean} [select=true] The desired selected state. - * - * @returns {boolean} true if the selected state changed, false otherwise. - */ - setSelected: function(select){ - // Null datums are always not selected - if(this.isNull){ return false; } - - // Normalize 'select' - select = (select == null) || !!select; - - var changed = this.isSelected !== select; - if(changed){ - if(!select){ - delete this.isSelected; - } else { - this.isSelected = true; - } - - - /*global data_onDatumSelectedChanged:true */ - data_onDatumSelectedChanged.call(this.owner, this, select); - } - - return changed; - }, - - /** - * Toggles the selected state of the datum. - * - * @type {undefined} - */ - toggleSelected: function(){ - return this.setSelected(!this.isSelected); - }, - - /** - * Sets the visible state of the datum to a specified value. - * - * @param {boolean} [visible=true] The desired visible state. - * - * @returns {boolean} true if the visible state changed, false otherwise. - */ - setVisible: function(visible){ - // Null datums are always visible - if(this.isNull){ return false; } - - // Normalize 'visible' - visible = (visible == null) || !!visible; - - var changed = this.isVisible !== visible; - if(changed){ - this.isVisible = visible; - //if(!this.isNull){ - /*global data_onDatumVisibleChanged:true */ - data_onDatumVisibleChanged.call(this.owner, this, visible); - //} - } - - return changed; - }, - - /** - * Toggles the visible state of the datum. - * - * @type {undefined} - */ - toggleVisible: function(){ - return this.setVisible(!this.isVisible); - } -}); - -/** - * Called by the owner data to clear the datum's selected state (internal). - * @name pvc.data.Datum#_deselect - * @function - * @type undefined - * @private - * - * @see pvc.data.Data#clearSelected - */ -function datum_deselect(){ - delete this.isSelected; -} diff --git a/pacotes/ccc2/pvc/data/Dimension.js b/pacotes/ccc2/pvc/data/Dimension.js deleted file mode 100755 index 1b8ccb2..0000000 --- a/pacotes/ccc2/pvc/data/Dimension.js +++ /dev/null @@ -1,1293 +0,0 @@ - -/** - * Initializes a dimension instance. - * - * @name pvc.data.Dimension - * - * @class A dimension holds unique atoms, - * of a given dimension type, - * and for a given data instance. - * - * @property {pvc.data.Data} data The data that owns this dimension. - * @property {pvc.data.DimensionType} type The dimension type of this dimension. - * @property {string} name Much convenient property with the name of {@link #type}. - * - * @property {pvc.data.Dimension} parent The parent dimension. - * A root dimension has a null parent. - * - * @property {pvc.data.Dimension} linkParent The link parent dimension. - * - * @property {pvc.data.Dimension} root The root dimension. - * A root dimension has itself as the value of {@link #root}. - * - * @property {pvc.data.Dimension} owner The owner dimension. - * An owner dimension is the topmost root dimension (accessible from this one). - * An owner dimension owns its atoms, while others simply contain them. - * The value of {@link pvc.data.Atom#dimension} is an atom's owner dimension. - * - * @constructor - * - * @param {pvc.data.Data} data The data that owns this dimension. - * @param {pvc.data.DimensionType} type The type of this dimension. - */ -def.type('pvc.data.Dimension') -.init(function(data, type){ - /* NOTE: this function is a hot spot and as such is performance critical */ - this.data = data; - this.type = type; - this.root = this; - this.owner = this; - - var name = type.name; - - this.name = name; - - // Cache - // ------- - // The atom id comparer ensures we keep atoms in the order they were added, - // even when no semantic comparer is provided. - // This is important, at least, to keep the visible atoms cache in the correct order. - this._atomComparer = type.atomComparer(); - this._atomsByKey = {}; - - if(data.isOwner()){ - // Owner - // Atoms are interned by #intern - this._atoms = []; - - dim_createVirtualNullAtom.call(this); - - } else { - // Not an owner - var parentData = data.parent; - - var source; // Effective parent / atoms source - if(parentData){ - // Not a root - source = parentData._dimensions[name]; - dim_addChild.call(source, this); - - this.root = data.parent.root; - } else { - parentData = data.linkParent; - // A root that is not topmost - /*jshint expr:true */ - parentData || def.assert("Data must have a linkParent"); - - source = parentData._dimensions[name]; - dim_addLinkChild.call(source, this); - } - - // Not in _atomsKey - this._nullAtom = this.owner._nullAtom; // may be null - - this._lazyInit = function(){ /* captures 'source' and 'name' variable */ - this._lazyInit = null; - - // Collect distinct atoms in data._datums - var datums = this.data._datums; - var L = datums.length; - var atomsByKey = this._atomsByKey; - for(var i = 0 ; i < L ; i++){ - // NOTE: Not checking if atom is already added, - // but it has no adverse side-effect. - var atom = datums[i].atoms[name]; - atomsByKey[atom.key] = atom; - } - - // Filter parentEf dimension's atoms; keeps order. - this._atoms = source.atoms().filter(function(atom){ - return def.hasOwnProp.call(atomsByKey, atom.key); - }); - }; - } -}) -.add(/** @lends pvc.data.Dimension# */{ - - parent: null, - - linkParent: null, - - /** - * The array of child dimensions. - * @type pvc.data.Dimension[] - */ - _children: null, - - /** - * The array of link child dimensions. - * @type pvc.data.Dimension[] - */ - _linkChildren: null, - - /** - * A map of the contained atoms by their {@link pvc.data.Atom#key} property. - * - * Supports the intern(...), atom(.), and the control of the visible atoms cache. - * - * @type object - */ - _atomsByKey: null, - - /** - * A map of the count of visible datums per atom {@link pvc.data.Atom#key} property. - * - * @type object - */ - _atomVisibleDatumsCount: null, - - /** - * Indicates if the object has been disposed. - * - * @type boolean - * @private - */ - _disposed: false, - - /** - * The atom with a null value. - * - * @type pvc.data.Atom - * @private - */ - _nullAtom: null, - - /** - * The virtual null atom. - * - *

- * This atom exists to resolve situations - * where a null atom does not exist in the loaded data. - * When a null datum is built, it may not specify - * all dimensions. When such an unspecified dimension - * is accessed the virtual null atom is returned by - * lookup of the atoms prototype chain (see {@link pvc.data.Data#_atomsBase}. - *

- * - * @type pvc.data.Atom - * @private - */ - _virtualNullAtom: null, - - /** - * Cache of sorted visible and invisible atoms. - * A map from visible state to {@link pvc.data.Atom[]}. - *

- * Cleared whenever any atom's "visible state" changes. - *

- * - * @type object - * @private - */ - _visibleAtoms: null, - - /** - * Cache of sorted visible and invisible indexes. - * A map from visible state to {@link number[]}. - *

- * Cleared whenever any atom's "visible state" changes. - *

- * - * @type object - * @private - */ - _visibleIndexes: null, - - /** - * Cache of the dimension type's normal order atom comparer. - * - * @type function - * @private - */ - _atomComparer: null, - - /** - * The ordered array of contained atoms. - *

- * The special null atom, if existent, is the first item in the array. - *

- *

- * On a child dimension it is a filtered version - * of the parent's array, - * and thus has the same atom relative order. - * - * In a link child dimension it is copy - * of the link parent's array. - *

- * - * @type pvc.data.Atom[] - * @see #_nullAtom - */ - _atoms: null, - - /** - * An object with cached results of the {@link #sum} method. - * - * @type object - */ - _sumCache: null, - - /** - * Obtains the number of atoms contained in this dimension. - * - *

- * Consider calling this method on the root or owner dimension. - *

- * - * @returns {Number} The number of contained atoms. - * - * @see pvc.data.Dimension#root - * @see pvc.data.Dimension#owner - */ - count: function(){ - if(this._lazyInit) { this._lazyInit(); } - return this._atoms.length; - }, - - /** - * Indicates if an atom belonging to this dimension - * is considered visible in it. - * - *

- * An atom is considered visible in a dimension - * if there is at least one datum of the dimension's data - * that has the atom and is visible. - *

- * - * @param {pvc.data.Atom} atom The atom of this dimension whose visible state is desired. - * - * @type boolean - */ - isVisible: function(atom){ - if(this._lazyInit) { this._lazyInit(); } - - // - /*jshint expr:true */ - def.hasOwn(this._atomsByKey, atom.key) || def.assert("Atom must exist in this dimension."); - // - - return dim_getVisibleDatumsCountMap.call(this)[atom.key] > 0; - }, - - /** - * Obtains the atoms contained in this dimension, - * possibly filtered. - * - *

- * Consider calling this method on the root or owner dimension. - *

- * - * @param {Object} [keyArgs] Keyword arguments. - * @param {boolean} [keyArgs.visible=null] - * Only considers atoms that - * have the specified visible state. - * - * @returns {pvc.data.Atom[]} An array with the requested atoms. - * Do NOT modify the returned array. - * - * @see pvc.data.Dimension#root - * @see pvc.data.Dimension#owner - */ - atoms: function(keyArgs){ - if(this._lazyInit) { this._lazyInit(); } - - var visible = def.get(keyArgs, 'visible'); - if(visible == null){ - return this._atoms; - } - - visible = !!visible; - - /*jshint expr:true */ - this._visibleAtoms || (this._visibleAtoms = {}); - - return this._visibleAtoms[visible] || - (this._visibleAtoms[visible] = dim_calcVisibleAtoms.call(this, visible)); - }, - - /** - * Obtains the local indexes of all, visible or invisible atoms. - * - * @param {Object} [keyArgs] Keyword arguments. - * @param {boolean} [keyArgs.visible=null] - * Only considers atoms that - * have the specified visible state. - * - * @type number[] - */ - indexes: function(keyArgs){ - if(this._lazyInit) { this._lazyInit(); } - - var visible = def.get(keyArgs, 'visible'); - if(visible == null) { - // Not used much so generate each time - return pv.range(0, this._atoms.length); - } - - visible = !!visible; - - /*jshint expr:true */ - this._visibleIndexes || (this._visibleIndexes = {}); - return this._visibleIndexes[visible] || - (this._visibleIndexes[visible] = dim_calcVisibleIndexes.call(this, visible)); - }, - - /** - * Obtains an atom that represents the specified value, if one exists. - * - * @param {any} value A value of the dimension type's {@link pvc.data.DimensionType#valueType}. - * - * @returns {pvc.data.Atom} The existing atom with the specified value, or null if there isn't one. - */ - atom: function(value){ - if(value == null || value === '') { - return this._nullAtom; // may be null - } - - if(value instanceof pvc.data.Atom) { - return value; - } - - if(this._lazyInit) { this._lazyInit(); } - - var key = this.type._key ? this.type._key.call(null, value) : value; - return this._atomsByKey[key] || null; // undefined -> null - }, - - /** - * Obtains the minimum and maximum atoms of the dimension, - * possibly filtered. - * - *

- * Assumes that the dimension type is comparable. - * If not the result will coincide with "first" and "last". - *

- * - *

- * Does not consider the null atom. - *

- * - *

- * Consider calling this method on the root or owner dimension. - *

- * - * @param {object} [keyArgs] Keyword arguments. - * See {@link #atoms} for additional keyword arguments. - * @param {boolean} [keyArgs.abs=false] Determines if the extent should consider the absolute value. - * - * @returns {object} - * An extent object with 'min' and 'max' properties, - * holding the minimum and the maximum atom, respectively, - * if at least one atom satisfies the selection; - * undefined otherwise. - * - * @see #root - * @see #owner - * @see #atoms - * @see pvc.data.DimensionType.isComparable - */ - extent: function(keyArgs){ - // Assumes atoms are sorted (null, if existent is the first). - var atoms = this.atoms(keyArgs); - var L = atoms.length; - if(!L){ return undefined; } - - var offset = this._nullAtom && atoms[0].value == null ? 1 : 0; - var countWithoutNull = L - offset; - if(countWithoutNull > 0){ - var min = atoms[offset]; - var max = atoms[L - 1]; - - // ------------------ - var tmp; - if(min !== max && def.get(keyArgs, 'abs', false)){ - var minSign = min.value < 0 ? -1 : 1; - var maxSign = max.value < 0 ? -1 : 1; - if(minSign === maxSign){ - if(maxSign < 0){ - tmp = max; - max = min; - min = tmp; - } - } else if(countWithoutNull > 2){ - // There's a third atom in between - // min is <= 0 - // max is >= 0 - // and, of course, min !== max - - // One of min or max has the biggest abs value - if(max.value < -min.value){ - max = min; - } - - // The smallest atom is the one in atoms that is closest to 0, possibly 0 itself - var zeroIndex = def.array.binarySearch(atoms, 0, this.type.comparer(), function(a){ return a.value; }); - if(zeroIndex < 0){ - zeroIndex = ~zeroIndex; - // Not found directly. - var negAtom = atoms[zeroIndex - 1]; - var posAtom = atoms[zeroIndex]; - if(-negAtom.value < posAtom.value){ - min = negAtom; - } else { - min = posAtom; - } - } else { - // Zero was found - // It is the minimum - min = atoms[zeroIndex]; - } - } else if(max.value < -min.value){ - // min is <= 0 - // max is >= 0 - // and, of course, min !== max - tmp = max; - max = min; - min = tmp; - } - } - - // ----------------- - - return {min: min, max: max}; - } - - return undefined; - }, - - /** - * Obtains the minimum atom of the dimension, - * possibly after filtering. - * - *

- * Assumes that the dimension type is comparable. - * If not the result will coincide with "first". - *

- * - *

- * Does not consider the null atom. - *

- * - *

- * Consider calling this method on the root or owner dimension. - *

- * - * @param {object} [keyArgs] Keyword arguments. - * See {@link #atoms} for a list of available filtering keyword arguments. - * - * @returns {pvc.data.Atom} The minimum atom satisfying the selection; - * undefined if none. - * - * @see #root - * @see #owner - * @see #atoms - * @see pvc.data.DimensionType.isComparable - */ - min: function(keyArgs){ - // Assumes atoms are sorted. - var atoms = this.atoms(keyArgs); - var L = atoms.length; - if(!L){ return undefined; } - - var offset = this._nullAtom && atoms[0].value == null ? 1 : 0; - return (L > offset) ? atoms[offset] : undefined; - }, - - /** - * Obtains the maximum atom of the dimension, - * possibly after filtering. - * - *

- * Assumes that the dimension type is comparable. - * If not the result will coincide with "last". - *

- * - *

- * Does not consider the null atom. - *

- * - *

- * Consider calling this method on the root or owner dimension. - *

- * - * @param {object} [keyArgs] Keyword arguments. - * See {@link #atoms} for a list of available filtering keyword arguments. - * - * @returns {pvc.data.Atom} The maximum atom satisfying the selection; - * undefined if none. - * - * @see #root - * @see #owner - * @see #atoms - * - * @see pvc.data.DimensionType.isComparable - */ - max: function(keyArgs){ - // Assumes atoms are sorted. - var atoms = this.atoms(keyArgs); - var L = atoms.length; - - return L && atoms[L - 1].value != null ? atoms[L - 1] : undefined; - }, - - /** - * Obtains the sum of this dimension's values over all datums of the data, - * possibly after filtering. - * - *

- * Assumes that the dimension type {@link pvc.data.DimensionType#valueType} is "Number". - *

- * - *

- * Does not consider the null atom. - *

- * - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.data.Data#datums} for a list of available filtering keyword arguments. - * - * @param {boolean} [keyArgs.abs=false] Indicates if it is the sum of the absolute value that is desired. - * @param {boolean} [keyArgs.zeroIfNone=true] Indicates that zero should be returned when there are no datums - * or no datums with non-null values. - * When false, null is returned, in that situation. - * - * @returns {number} The sum of considered datums or 0 or null, if none. - * - * @see #root - * @see #owner - * @see #atoms - */ - sum: function(keyArgs){ - var isAbs = !!def.get(keyArgs, 'abs', false), - zeroIfNone = def.get(keyArgs, 'zeroIfNone', true), - key = dim_buildDatumsFilterKey(keyArgs) + ':' + isAbs; - - var sum = def.getOwn(this._sumCache, key); - if(sum === undefined) { - var dimName = this.name; - sum = this.data.datums(null, keyArgs).reduce(function(sum2, datum){ - var value = datum.atoms[dimName].value; - if(isAbs && value < 0){ // null < 0 is false - value = -value; - } - - return sum2 != null ? (sum2 + value) : value; // null preservation - }, - null); - - (this._sumCache || (this._sumCache = {}))[key] = sum; - } - - return zeroIfNone ? (sum || 0) : sum; - }, - - /** - * Obtains the percentage of a specified atom or value, - * over the sum of the absolute values of a specified datum set. - * - *

- * Assumes that the dimension type {@link pvc.data.DimensionType#valueType} is "Number". - *

- * - *

- * Does not consider the null atom. - *

- * - * @param {pvc.data.Atom|any} [atomOrValue] The atom or value on which to calculate the percent. - * - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.data.Dimension#sum} for a list of available filtering keyword arguments. - * - * @returns {number} The calculated percentage. - * - * @see #root - * @see #owner - */ - percent: function(atomOrValue, keyArgs){ - var value = (atomOrValue instanceof pvc.data.Atom) ? atomOrValue.value : atomOrValue; - if(!value) { // nully or zero - return 0; - } - // if value != 0 => sum != 0, but JIC, we test for not 0... - var sum = this.sum(def.create(keyArgs, {abs: true})); - return sum ? (Math.abs(value) / sum) : 0; - }, - - /** - * Obtains the percentage of the local sum of a specified selection, - * over the sum of the absolute values of an analogous selection in the parent data. - * - *

- * Assumes that the dimension type {@link pvc.data.DimensionType#valueType} is "Number". - *

- * - *

- * Does not consider the null atom. - *

- * - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.data.Dimension#sum} for a list of available filtering keyword arguments. - * - * @returns {number} The calculated percentage. - * - * @see #root - * @see #owner - */ - percentOverParent: function(keyArgs){ - var value = this.sum(keyArgs); // normal sum - if(!value) { // nully or zero - return 0; - } - - // if value != 0 => sum != 0, but JIC, we test for not 0... - var parentData = this.data.parent; - if(!parentData) { - return 0; - } - - // The following would not work because, in each group, - // abs would not be used... - //var sum = parentData.dimensions(this.name).sum(); - - var sum = parentData.dimensionsSumAbs(this.name, keyArgs); - - return sum ? (Math.abs(value) / sum) : 0; - }, - - - format: function(value, sourceValue){ - return "" + (this.type._formatter ? this.type._formatter.call(null, value, sourceValue) : ""); - }, - - /** - * Obtains an atom that represents the specified sourceValue, - * creating one if one does not yet exist. - * - *

- * Used by a translation to - * obtain atoms of a dimension for raw values of source items. - *

- *

- * If this method is not called on an owner dimension, - * and if the requested values isn't locally present, - * the call is recursively forwarded to the dimension's - * parent or link parent until the atom is found. - * Ultimately, if the atom does not yet exist, - * it is created in the owner dimension. - *

- *

- * An empty string value is considered equal to a null value. - *

- * @param {any | pvc.data.Atom} sourceValue The source value. - * @param {boolean} [isVirtual=false] Indicates that - * the (necessarily non-null) atom is the result of interpolation or regression. - * - * @type pvc.data.Atom - */ - intern: function(sourceValue, isVirtual){ - // NOTE: This function is performance critical! - - // The null path and the existing atom path - // are as fast and direct as possible - - // - NULL - - if(sourceValue == null || sourceValue === '') { - return this._nullAtom || dim_createNullAtom.call(this, sourceValue); - } - - if(sourceValue instanceof pvc.data.Atom){ - if(sourceValue.dimension !== this){ - throw def.error.operationInvalid("Atom is of a different dimension."); - } - - return sourceValue; - } - - var value, label; - var type = this.type; - - // Is google table style cell {v: , f: } ? - if(typeof sourceValue === 'object' && ('v' in sourceValue)){ - // Get info and get rid of the cell - label = sourceValue.f; - sourceValue = sourceValue.v; - } - - // - CONVERT - - if(!isVirtual){ - var converter = type._converter; - value = converter ? converter(sourceValue) : sourceValue; - if(value == null || value === '') { - // Null after all - return this._nullAtom || dim_createNullAtom.call(this, sourceValue); - } - } else { - value = sourceValue; - } - - // - CAST - - // Any cast function? - var cast = type.cast; - if(cast) { - value = cast(value); - if(value == null || value === ''){ - // Null after all (normally a cast failure) - return this._nullAtom || dim_createNullAtom.call(this); - } - } - - // - KEY - - var keyFun = type._key; - var key = '' + (keyFun ? keyFun(value) : value); - // - /*jshint expr:true */ - key || def.fail.operationInvalid("Only a null value can have an empty key."); - // - - // - ATOM - - var atom = this._atomsByKey[key]; - if(atom){ - if(!isVirtual && atom.isVirtual){ - delete atom.isVirtual; - } - return atom; - } - - return dim_createAtom.call( - this, - type, - sourceValue, - key, - value, - label, - isVirtual); - }, - - /** - * Disposes the dimension and all its children. - */ - dispose: function(){ - if(!this._disposed){ - /*global data_disposeChildList:true */ - data_disposeChildList(this._children, 'parent'); - data_disposeChildList(this._linkChildren, 'linkParent'); - - // myself - - if(this.parent) { dim_removeChild.call(this.parent, this); } - if(this.linkParent) { dim_removeLinkChild.call(this.linkParent, this); } - - dim_clearVisiblesCache.call(this); - - this._lazyInit = null; - - this._atoms = - this._nullAtom = - this._virtualNullAtom = null; - - this._disposed = true; - } - } -}); - -/** - * Creates an atom, - * in the present dimension if it is the owner dimension, - * or delegates the creation to its parent, or linked parent dimension. - * - * The atom must not exist in the present dimension. - * - * @name pvc.data.Dimension#_createAtom - * @function - * @param {pvc.data.DimensionType} type The dimension type of this dimension. - * @param {any} sourceValue The source value. - * @param {string} key The key of the value. - * @param {any} value The typed value. - * @param {string} [label] The label, if it is present directly - * in {@link sourceValue}, in Google format. - * @type pvc.data.Atom - */ -function dim_createAtom(type, sourceValue, key, value, label, isVirtual){ - var atom; - if(this.owner === this){ - // Create the atom - - // - LABEL - - if(label == null){ - var formatter = type._formatter; - if(formatter){ - label = formatter(value, sourceValue); - } else { - label = value; - } - } - - label = "" + label; // J.I.C. - - if(!label && pvc.debug >= 2){ - pvc.log("Only the null value should have an empty label."); - } - - // - ATOM! - - atom = new pvc.data.Atom(this, value, label, sourceValue, key); - if(isVirtual){ - atom.isVirtual = true; - } - } else { - var source = this.parent || this.linkParent; - atom = source._atomsByKey[key] || - dim_createAtom.call( - source, - type, - sourceValue, - key, - value, - label, - isVirtual); - } - - // Insert atom in order (or at the end when !_atomComparer) - def.array.insert(this._atoms, atom, this._atomComparer); - - dim_clearVisiblesCache.call(this); - - this._atomsByKey[key] = atom; - - return atom; -} - -/** - * Ensures that the specified atom exists in this dimension. - * The atom must have been created in a dimension of this dimension tree. - * - * If the virtual null atom is found it is replaced by the null atom, - * meaning that, after all, the null is really present in the data. - * - * @param {pvc.data.Atom} atom the atom to intern. - * - * @name pvc.data.Dimension#_internAtom - * @function - * @type pvc.data.Atom - */ -function dim_internAtom(atom){ - var key = atom.key; - - // Root load will fall in this case - if(atom.dimension === this){ - /*jshint expr:true */ - (this.owner === this) || def.assert("Should be an owner dimension"); - - if(!key && atom === this._virtualNullAtom){ - /* This indicates that there is a dimension for which - * there was no configured reader, - * so nulls weren't read. - * - * We will register the real null, - * and the virtual null atom will not show up again, - * because it appears through the prototype chain - * as a default value. - */ - atom = this.intern(null); - } - - return atom; - } - - if(!this._lazyInit){ - // Else, not yet initialized, so there's no need to add the atom now - var localAtom = this._atomsByKey[key]; - if(localAtom){ - if(localAtom !== atom){ - throw def.error.operationInvalid("Atom is from a different root data."); - } - - return atom; - } - - if(this.owner === this) { - // Should have been created in a dimension along the way. - throw def.error.operationInvalid("Atom is from a different root data."); - } - } - - dim_internAtom.call(this.parent || this.linkParent, atom); - - if(!this._lazyInit){ - // Insert atom in order (or at the end when !_atomComparer) - this._atomsByKey[key] = atom; - - if(!key){ - this._nullAtom = atom; - this._atoms.unshift(atom); - } else { - def.array.insert(this._atoms, atom, this._atomComparer); - } - - dim_clearVisiblesCache.call(this); - } - - return atom; -} - -/** - * Builds a key string suitable for identifying a call to {@link pvc.data.Data#datums} - * with no where specification. - * - * @name pvc.data.Dimension#_buildDatumsFilterKey - * @function - * @param {object} [keyArgs] The keyword arguments used in the call to {@link pvc.data.Data#datums}. - * @type string - */ -function dim_buildDatumsFilterKey(keyArgs){ - var visible = def.get(keyArgs, 'visible'), - selected = def.get(keyArgs, 'selected'); - return (visible == null ? null : !!visible) + ':' + (selected == null ? null : !!selected); -} - -/** - * Creates the null atom if it isn't created yet. - * - * @name pvc.data.Dimension#_createNullAtom - * @function - * @param {any} [sourceValue] The source value of null. Can be used to obtain the null format. - * @type undefined - * @private - */ -function dim_createNullAtom(sourceValue){ - var nullAtom = this._nullAtom; - if(!nullAtom){ - if(this.owner === this){ - var typeFormatter = this.type._formatter; - var label = "" + (typeFormatter ? typeFormatter.call(null, null, sourceValue) : ""); - - nullAtom = new pvc.data.Atom(this, null, label, null, ''); - - this.data._atomsBase[this.name] = nullAtom; - } else { - // Recursively set the null atom, up the parent/linkParent chain - // until reaching the owner (root) dimension. - nullAtom = dim_createNullAtom.call(this.parent || this.linkParent, sourceValue); - } - - this._atomsByKey[''] = this._nullAtom = nullAtom; - - // The null atom is always in the first position - this._atoms.unshift(nullAtom); - } - - return nullAtom; -} - -/** - * Creates the virtual null atom if it isn't created yet. - * - * @name pvc.data.Dimension#_createNullAtom - * @function - * @type undefined - * @private - */ -function dim_createVirtualNullAtom(){ - // - /*jshint expr:true */ - (this.owner === this) || def.assert("Can only create atoms on an owner dimension."); - // - - if(!this._virtualNullAtom){ - // The virtual null's label is always "". - // Don't bother the formatter with a value that - // does not exist in the data. - this._virtualNullAtom = new pvc.data.Atom(this, null, "", null, ''); - - this.data._atomsBase[this.name] = this._virtualNullAtom; - } - - return this._virtualNullAtom; -} - -/** - * Uninternalizes the specified atom from the dimension (internal). - * - * @name pvc.data.Dimension#_unintern - * @function - * @param {pvc.data.Atom} The atom to uninternalize. - * @type undefined - * @private - * @internal - */ -function dim_unintern(atom){ - // - /*jshint expr:true */ - (this.owner === this) || def.assert("Can only unintern atoms on an owner dimension."); - (atom && atom.dimension === this) || def.assert("Not an interned atom"); - // - - if(atom === this._virtualNullAtom){ - return; - } - - // Remove the atom - var key = atom.key; - if(this._atomsByKey[key] === atom){ - def.array.remove(this._atoms, atom, this._atomComparer); - delete this._atomsByKey[key]; - - if(!key){ - delete this._nullAtom; - this.data._atomsBase[this.name] = this._virtualNullAtom; - } - } - - dim_clearVisiblesCache.call(this); -} - -function dim_uninternUnvisitedAtoms(){ - // - /*jshint expr:true */ - (this.owner === this) || def.assert("Can only unintern atoms of an owner dimension."); - // - - var atoms = this._atoms; - if(atoms){ - var atomsByKey = this._atomsByKey; - var i = 0; - var L = atoms.length; - while(i < L){ - var atom = atoms[i]; - if(atom.visited){ - delete atom.visited; - i++; - } else if(atom !== this._virtualNullAtom) { - // Remove the atom - atoms.splice(i, 1); - L--; - - var key = atom.key; - delete atomsByKey[key]; - if(!key){ - delete this._nullAtom; - this.data._atomsBase[this.name] = this._virtualNullAtom; - } - } - } - - dim_clearVisiblesCache.call(this); - } -} - -function dim_uninternVirtualAtoms(){ - // This assumes that this same function has been called on child/link child dimensions - var atoms = this._atoms; - if(atoms){ - var atomsByKey = this._atomsByKey; - var i = 0; - var L = atoms.length; - var removed; - while(i < L){ - var atom = atoms[i]; - if(!atom.isVirtual){ - i++; - } else { - // Remove the atom - atoms.splice(i, 1); - L--; - removed = true; - var key = atom.key || def.assert("Cannot be the null or virtual null atom."); - delete atomsByKey[key]; - } - } - - if(removed){ - dim_clearVisiblesCache.call(this); - } - } -} - -/** - * Clears all caches affected by datum/atom visibility. - * - * @name pvc.data.Dimension#_clearVisiblesCache - * @function - * @type undefined - * @private - * @internal - */ -function dim_clearVisiblesCache(){ - this._atomVisibleDatumsCount = - this._sumCache = - this._visibleAtoms = - this._visibleIndexes = null; -} - -/** - * Called by a dimension's data when its datums have changed. - * - * @name pvc.data.Dimension#_onDatumsChanged - * @function - * @type undefined - * @private - * @internal - */ -function dim_onDatumsChanged(){ - dim_clearVisiblesCache.call(this); -} - -/** - * Adds a child dimension. - * - * @name pvc.data.Dimension#_addChild - * @function - * @param {pvc.data.Dimension} child The child to add. - * @type undefined - * @private - */ -function dim_addChild(child){ - /*global data_addColChild:true */ - data_addColChild(this, '_children', child, 'parent'); - - child.owner = this.owner; -} - -/** - * Removes a child dimension. - * - * @name pvc.data.Dimension#_removeChild - * @function - * @param {pvc.data.Dimension} child The child to remove. - * @type undefined - * @private - */ -function dim_removeChild(child){ - /*global data_removeColChild:true */ - data_removeColChild(this, '_children', child, 'parent'); -} - -/** - * Adds a link child dimension. - * - * @name pvc.data.Dimension#_addLinkChild - * @function - * @param {pvc.data.Dimension} child The link child to add. - * @type undefined - * @private - */ -function dim_addLinkChild(linkChild){ - data_addColChild(this, '_linkChildren', linkChild, 'linkParent'); - - linkChild.owner = this.owner; -} - -/** - * Removes a link child dimension. - * - * @name pvc.data.Dimension#_removeLinkChild - * @function - * @param {pvc.data.Dimension} linkChild The child to remove. - * @type undefined - * @private - */ -function dim_removeLinkChild(linkChild){ - data_removeColChild(this, '_linkChildren', linkChild, 'linkParent'); -} - -/** - * Called by the data of this dimension when - * the visible state of a datum has changed. - * - * @name pvc.data.Dimension#_onDatumVisibleChanged - * @function - * @type undefined - * @private - * @internal - */ -function dim_onDatumVisibleChanged(datum, visible) { - var map; - if(!this._disposed && (map = this._atomVisibleDatumsCount)) { - var atom = datum.atoms[this.name], - key = atom.key; - - // - /*jshint expr:true */ - def.hasOwn(this._atomsByKey, key) || def.assert("Atom must exist in this dimension."); - // - - var count = map[key]; - - // - (visible || (count > 0)) || def.assert("Must have had accounted for at least one visible datum."); - // - - map[key] = (count || 0) + (visible ? 1 : -1); - - // clear dependent caches - this._visibleAtoms = - this._sumCache = - this._visibleIndexes = null; - } -} - -/** - * Obtains the map of visible datums count per atom, - * creating the map if necessary. - * - * @name pvc.data.Dimension#_getVisibleDatumsCountMap - * @function - * @type undefined - * @private - */ -function dim_getVisibleDatumsCountMap() { - var map = this._atomVisibleDatumsCount; - if(!map) { - map = {}; - - this.data.datums(null, {visible: true}).each(function(datum){ - var atom = datum.atoms[this.name], - key = atom.key; - map[key] = (map[key] || 0) + 1; - }, this); - - this._atomVisibleDatumsCount = map; - } - - return map; -} - -/** - * Calculates the list of indexes of visible or invisible atoms. - *

- * Does not include the null atom. - *

- * - * @name pvc.data.Dimension#_calcVisibleIndexes - * @function - * @param {boolean} visible The desired atom visible state. - * @type number[] - * @private - */ -function dim_calcVisibleIndexes(visible){ - var indexes = []; - - this._atoms.forEach(function(atom, index){ - if(this.isVisible(atom) === visible) { - indexes.push(index); - } - }, this); - - return indexes; -} - -/** - * Calculates the list of visible or invisible atoms. - *

- * Does not include the null atom. - *

- * - * @name pvc.data.Dimension#_calcVisibleAtoms - * @function - * @param {boolean} visible The desired atom visible state. - * @type number[] - * @private - */ -function dim_calcVisibleAtoms(visible){ - return def.query(this._atoms) - .where(function(atom){ return this.isVisible(atom) === visible; }, this) - .array(); -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/GroupingOper.js b/pacotes/ccc2/pvc/data/GroupingOper.js deleted file mode 100755 index 03a817b..0000000 --- a/pacotes/ccc2/pvc/data/GroupingOper.js +++ /dev/null @@ -1,482 +0,0 @@ - -/** - * Initializes a grouping operation. - * - * @name pvc.data.GroupingOper - * - * @class Performs one grouping operation according to a grouping specification. - * @extends pvc.data.DataOper - * - * @constructor - * - * @param {pvc.data.Data} linkParent The link parent data. - * - * @param {string|string[]|pvc.data.GroupingSpec|pvc.data.GroupingSpec[]} groupingSpecs A grouping specification as a string, an object or array of either. - * - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.data.DataOper} for any additional arguments. - * - * @param {boolean} [keyArgs.isNull=null] - * Only considers datums with the specified isNull attribute. - * @param {boolean} [keyArgs.visible=null] - * Only considers datums that have the specified visible state. - * @param {boolean} [keyArgs.selected=null] - * Only considers datums that have the specified selected state. - * @param {function} [keyArgs.where] A datum predicate. - * @param {string} [keyArgs.whereKey] A key for the specified datum predicate, - * previously returned by this function. - *

- * If this argument is specified, and it is not the value null, - * it can be used to cache results. - * If this argument is specified, and it is the value null, - * the results are not cached. - * If it is not specified, and keyArgs is specified, - * one is returned. - * If it is not specified and keyArgs is not specified, - * then the instance will have a null {@link #key} property value. - *

- *

- * If a key not previously returned by this operation is specified, - * then it should be prefixed with a "_" character, - * in order to not collide with keys generated internally. - *

- */ -def.type('pvc.data.GroupingOper', pvc.data.DataOper) -.init(function(linkParent, groupingSpecs, keyArgs){ - /* Grouping spec may be specified as text or object */ - /*jshint expr:true */ - groupingSpecs || def.fail.argumentRequired('groupingSpecs'); - - this.base(linkParent, keyArgs); - - this._where = def.get(keyArgs, 'where'); - this._visible = def.get(keyArgs, 'visible', null); - this._selected = def.get(keyArgs, 'selected', null); - this._isNull = def.get(keyArgs, 'isNull', null); - - /* 'Where' predicate and its key */ - var hasKey = this._selected == null, // TODO: Selected state changes do not yet invalidate cache... - whereKey = ''; - if(this._where){ - whereKey = def.get(keyArgs, 'whereKey'); - if(!whereKey){ - if(!keyArgs || whereKey === null){ - // Force no key - hasKey = false; - } else { - whereKey = '' + def.nextId('dataOperWhereKey'); - keyArgs.whereKey = whereKey; - } - } - } - - // grouping spec ids is semantic keys, although the name is not 'key' - var ids = []; - this._groupSpecs = def.array.as(groupingSpecs).map(function(groupSpec){ - if(groupSpec instanceof pvc.data.GroupingSpec) { - if(groupSpec.type !== linkParent.type) { - throw def.error.argumentInvalid('groupingSpecText', "Invalid associated complex type."); - } - } else { - // Must be a non-empty string, or throws - groupSpec = pvc.data.GroupingSpec.parse(groupSpec, linkParent.type); - } - - ids.push(groupSpec.id); - - return groupSpec; - }); - - /* Operation key */ - if(hasKey){ - this.key = ids.join('!!') + - "||visible:" + this._visible + - "||isNull:" + this._isNull + - //"||selected:" + this._selected + - "||where:" + whereKey; - } -}). -add(/** @lends pvc.data.GroupingOper */{ - - /** - * Performs the grouping operation. - * - * @returns {pvc.data.Data} The resulting root data. - */ - execute: function(){ - /* Setup a priori datum filters */ - - /*global data_whereState: true */ - var datumsQuery = data_whereState(def.query(this._linkParent._datums), { - visible: this._visible, - selected: this._selected, - isNull: this._isNull, - where: this._where - }); - - /* Group datums */ - var rootNode = this._group(datumsQuery); - - /* Render node into a data */ - return this._generateData(rootNode, null, this._linkParent); - }, - - executeAdd: function(rootData, datums){ - - /*global data_whereState: true */ - var datumsQuery = data_whereState(def.query(datums), { - visible: this._visible, - selected: this._selected, - isNull: this._isNull, - where: this._where - }); - - /* Group new datums */ - var rootNode = this._group(datumsQuery); - - /* Render node into specified root data */ - this._generateData(rootNode, null, this._linkParent, rootData); - - return rootNode.datums; - }, - - _group: function(datumsQuery){ - - // Create the root node - var rootNode = { - isRoot: true, - treeHeight: def - .query(this._groupSpecs) - .select(function(spec){ - var levelCount = spec.levels.length; - if(!levelCount) { - return 0; - } - return !!spec.flatteningMode ? 1 : levelCount; - }) - .reduce(def.add, 0), - - datums: [] - // children - // atoms // not on rootNode - // isFlattenGroup // on parents of a flattened group spec - }; - - if(rootNode.treeHeight > 0){ - this._groupSpecRecursive(rootNode, datumsQuery, 0); - } - - return rootNode; - }, - - _groupSpecRecursive: function(specParentNode, specDatumsQuery, specIndex){ - var groupSpec = this._groupSpecs[specIndex]; - var levelSpecs = groupSpec.levels; - var L = levelSpecs.length; - var doFlatten = !!groupSpec.flatteningMode; - var nextSpecIndex = specIndex + 1; - var isLastSpec = (nextSpecIndex >= this._groupSpecs.length); - var isPostOrder = doFlatten && (groupSpec.flatteningMode === 'tree-post'); - var specGroupParent; - - if(doFlatten){ - specParentNode.children = []; - specParentNode.childrenByKey = {}; // Don't create children with equal keys - - // Must create a rootNode for the grouping operation - // Cannot be specParentNode (TODO: Why?) - specGroupParent = { - key: '', // Key is local to groupSpec (when not flattened, it is local to level) - absKey: '', - atoms: {}, - datums: [], - label: groupSpec.flattenRootLabel, - dimNames: [] - }; - - if(!isPostOrder){ - specParentNode.children.push(specGroupParent); - specParentNode.childrenByKey[''] = specGroupParent; - } - } else { - specGroupParent = specParentNode; - } - - /* Group datums */ - groupLevelRecursive.call(this, specGroupParent, specDatumsQuery, 0); - - if(doFlatten){ - - if(isPostOrder){ - specParentNode.children.push(specGroupParent); - } - - // Add datums of specGroupParent to specParentNode. - specParentNode.datums = specGroupParent.datums; - } - - function groupLevelRecursive(levelParentNode, levelDatums, levelIndex){ - - var levelSpec = levelSpecs[levelIndex]; - - if(!doFlatten){ - levelParentNode.children = []; - levelParentNode.groupSpec = groupSpec; - levelParentNode.groupLevelSpec = levelSpec; - } - - var childNodes = this._groupDatums(levelSpec, levelParentNode, levelDatums, doFlatten); - var isLastSpecLevel = levelIndex === L - 1; - var willRecurseParent = doFlatten && !isLastSpec; - - // Add children's datums to levelParentNode, in post order. - // This way, datums are reordered to follow the grouping "pattern". - // - // NOTE: levelParentNode.datums is initially empty - var levelParentDatums = willRecurseParent ? - [] : - levelParentNode.datums; - - childNodes - .forEach(function(child){ - /* On all but the last level, - * the datums of *child* are set to the - * union of datums of its own children. - * The datums will have been added, - * by the end of the following recursive call. - */ - var childDatums = child.datums; // backup original datums - if(!(isLastSpec && isLastSpecLevel)){ - child.datums = []; - } - - var specParentChildIndex; - if(!doFlatten){ - levelParentNode.children.push(child); - } else { - // Add children at a "hidden" property - // so that the test "if(!child._children.length)" - // below, can be done. - def.array.lazy(levelParentNode, '_children').push(child); - - if(def.hasOwn(specParentNode.childrenByKey, child.key)){ - // Duplicate key. - // Don't add as child of specParentNode. - // - // We need to add its datums to group parent, anyway. - def.array.append(levelParentDatums, childDatums); - return; - } - - specParentChildIndex = specParentNode.children.length; - if(!isPostOrder){ - specParentNode.children.push(child); - specParentNode.childrenByKey[child.key] = child; - - levelParentNode.isFlattenGroup = true; - } - } - - if(!isLastSpecLevel){ - groupLevelRecursive.call(this, child, childDatums, levelIndex + 1); - } else if(!isLastSpec) { - this._groupSpecRecursive(child, childDatums, nextSpecIndex); - } - - // Datums already added to 'child'. - def.array.append(levelParentDatums, child.datums); - - if(doFlatten && isPostOrder){ - if(def.hasOwn(specParentNode.childrenByKey, child.key)){ - /*jshint expr:true*/ - child.isFlattenGroup || def.assert("Must be a parent for duplicate keys to exist."); - - // A child of child - // was registered with the same key, - // because it is all-nulls (in descending level's keys). - // But it is better to show the parent instead of the child, - // so we remove the child and add the parent. - // Yet, we cannot show only the parent - // if *child* has more than one child, - // cause then, the datums of the null child.child - // would only be in *child*, but - // the datums of the non-null child.child - // would be both in *child* and in child.child. - // This would mess up the scales and waterfall control code, - // not knowing whether to ignore the flatten group or not. - if(child._children.length === 1){ - specParentNode.children.splice( - specParentChildIndex, - specParentNode.children.length - specParentChildIndex); - - // A total group that must be accounted for - // because it has own datums. - child.isDegenerateFlattenGroup = true; - } - // else, both are added to specParentNode, - // and their datas will be given separate keys - // they will both be shown. - // Below, we overwrite anyway, with no harmful effect - } - - specParentNode.children.push(child); - specParentNode.childrenByKey[child.key] = child; - - levelParentNode.isFlattenGroup = true; - } - }, this); - - if(willRecurseParent) { - // datums can no longer change - this._groupSpecRecursive(levelParentNode, levelParentDatums, nextSpecIndex); - } - } - }, - - _groupDatums: function(levelSpec, levelParentNode, levelDatums, doFlatten){ - // The first datum of each group is inserted here in order, - // according to the level's comparer. - var firstDatums = []; - - // The first child is inserted here - // at the same index as that of - // the first datum in firstDatums. - var childNodes = new def.OrderedMap(); - - // Group levelDatums By the levelSpec#key(.) - def - .query(levelDatums) - .each(function(datum){ - /* newChild = { key: '', atoms: {}, dimNames: [] } */ - var newChild = levelSpec.key(datum); - var key = newChild.key; - var child = childNodes.get(key); - if(child){ - child.datums.push(datum); - } else { - // First datum with key -> new child - child = newChild; - child.datums = [datum]; - - if(doFlatten){ - // child.atoms must contain (locally) those of the levelParentNode, - // so that when flattened, they have a unique key - def.copy(child.atoms, levelParentNode.atoms); - - // The key is the absKey, trimmed of keySep at the end - if(levelParentNode.dimNames.length){ -// child.key = levelParentNode.key + -// datum.owner.keySep + -// key; - - var keySep = datum.owner.keySep; - - child.absKey = - levelParentNode.absKey + - keySep + - key; - - var K = keySep.length; - var trimKey = child.absKey; - while(trimKey.lastIndexOf(keySep) === trimKey.length - K){ - trimKey = trimKey.substr(0, trimKey.length - K); - } - - child.key = trimKey; - } else { - child.absKey = key; - } - - // don't change local key variable - child.dimNames = levelSpec.accDimensionNames(); - } - - var datumIndex = def.array.insert(firstDatums, datum, levelSpec.comparer); - childNodes.add(key, child, ~datumIndex); - } - }); - - return childNodes; - }, - - _generateData: function(node, parentNode, parentData, rootData){ - var data, isNew; - if(node.isRoot){ - // Root node - if(rootData){ - data = rootData; - /*global data_addDatumsLocal:true*/ - data_addDatumsLocal.call(data, node.datums); - } else { - isNew = true; - - // Create a *linked* rootNode data - data = new pvc.data.Data({ - linkParent: parentData, - datums: node.datums - }); - data.treeHeight = node.treeHeight; - data._groupOper = this; - } - } else { - if(rootData){ - data = def.get(parentData._childrenByKey, node.key); - if(data){ - // Add the datums to the data, and its atoms to its dimensions - // Should also update linkedChildren (not children). - /*global data_addDatumsSimple:true*/ - data_addDatumsSimple.call(data, node.datums); - } - } - - if(!data){ - isNew = true; - var index, siblings; - if(rootData && (siblings = parentData._children)){ - // Insert the new sibling in correct order - // node.datums[0] is representative of the new Data's position - index = ~def.array.binarySearch(siblings, node.datums[0], parentNode.groupLevelSpec.comparer); - } - - data = new pvc.data.Data({ - parent: parentData, - atoms: node.atoms, - dimNames: node.dimNames, - datums: node.datums, - index: index - }); - } - } - - if(isNew && node.isFlattenGroup){ - data._isFlattenGroup = true; - data._isDegenerateFlattenGroup = !!node.isDegenerateFlattenGroup; - - var label = node.label; - if(label){ - data.label += label; - data.absLabel += label; - } - } - - var childNodes = node.children; - if(childNodes && childNodes.length){ - if(isNew){ - data._groupSpec = node.groupSpec; - data._groupLevelSpec = node.groupLevelSpec; - } - - childNodes.forEach(function(childNode){ - this._generateData(childNode, node, data, rootData); - }, this); - - } else if(isNew && !node.isRoot){ - // A leaf node - var leafs = data.root._leafs; - data.leafIndex = leafs.length; - leafs.push(data); - } - - return data; - } -}); diff --git a/pacotes/ccc2/pvc/data/GroupingSpec.js b/pacotes/ccc2/pvc/data/GroupingSpec.js deleted file mode 100755 index 112e7ca..0000000 --- a/pacotes/ccc2/pvc/data/GroupingSpec.js +++ /dev/null @@ -1,467 +0,0 @@ - -/** - * Initializes a grouping specification. - * - *

- * A grouping specification contains information similar to that of an SQL 'order by' clause. - *

- * - *

- * A grouping specification supports the grouping operation. - *

- * - * @see pvc.data.GroupingOper - * - * @name pvc.data.GroupingSpec - * - * @class Contains information about a grouping operation. - * - * @property {string} id A semantic identifier of this grouping specification. - * @property {boolean} isSingleDimension Indicates that there is only one level and dimension. - * @property {boolean} isSingleLevel Indicates that there is only one level. - * @property {boolean} hasCompositeLevels Indicates that there is at least one level with more than one dimension. - * @property {pvc.data.ComplexType} type The complex type against which dimension names were resolved. - * @property {pvc.data.GroupingLevelSpec} levels An array of level specifications. - * @property {pvc.data.DimensionType} firstDimension The first dimension type, if any. - * @property {string} flatteningMode Indicates if the grouping is - * flattened using pre or post order depth-first search. - * Possible values are null, 'tree-pre' and 'tree-post'. - * @property {string} flattenRootLabel The label of the root node of a flattening operation. - * - * @constructor - * @param {def.Query} levelSpecs An enumerable of {@link pvc.data.GroupingLevelSpec}. - * @param {pvc.data.ComplexType} [type] A complex type. - * @param {object} [keyArgs] Keyword arguments. - * @param {string} [keyArgs.flatteningMode=null] The flattening mode. - * @param {string} [keyArgs.flattenRootLabel=''] The label of the root node of a flattening operation. - */ -def.type('pvc.data.GroupingSpec') -.init(function(levelSpecs, type, keyArgs){ - this.type = type || null; - - var ids = []; - - this.hasCompositeLevels = false; - - var dimNames = []; // accumulated dimension names - - this.levels = def.query(levelSpecs || undefined) // -> null query - .where(function(levelSpec){ return levelSpec.dimensions.length > 0; }) - .select(function(levelSpec){ - ids.push(levelSpec.id); - - def.array.append(dimNames, levelSpec.dimensionNames()); - - if(!this.hasCompositeLevels && levelSpec.dimensions.length > 1) { - this.hasCompositeLevels = true; - } - - levelSpec._setAccDimNames(dimNames.slice(0)); - - return levelSpec; - }, this) - .array(); - - this._dimNames = dimNames; - - // The null grouping has zero levels - this.depth = this.levels.length; - this.isSingleLevel = this.depth === 1; - this.isSingleDimension = this.isSingleLevel && !this.hasCompositeLevels; - this.firstDimension = this.depth > 0 ? this.levels[0].dimensions[0] : null; - - this.flatteningMode = def.get(keyArgs, 'flatteningMode' ) || null; - this.flattenRootLabel = def.get(keyArgs, 'flattenRootLabel') || ''; - - this.id = (this.flatteningMode || '') + "##" + - this.flattenRootLabel + "##" + - ids.join('||'); -}) -.add(/** @lends pvc.data.GroupingSpec# */{ - /** - * Late binds a grouping specification to a complex type. - * @param {pvc.data.ComplexType} type A complex type. - */ - bind: function(type){ - this.type = type || def.fail.argumentRequired('type'); - this.levels.forEach(function(levelSpec){ - levelSpec.bind(type); - }); - }, - - /** - * Obtains an enumerable of the contained dimension specifications. - * @type def.Query - */ - dimensions: function(){ - return def.query(this.levels) - .selectMany(function(level){ return level.dimensions; }); - }, - - dimensionNames: function(){ - return this._dimNames; - }, - - view: function(complex){ - return complex.view(this.dimensionNames()); - }, - - /** - * Indicates if the data resulting from the grouping is discrete or continuous. - * @type boolean - */ - isDiscrete: function(){ - var d; - return !this.isSingleDimension || - (!!(d = this.firstDimension) && d.type.isDiscrete); - }, - - /** - * Obtains the dimension type of the first dimension spec., if any. - * @type pvc.visual.DimensionType - */ - firstDimensionType: function(){ - var d = this.firstDimension; - return d && d.type; - }, - - /** - * Obtains the dimension name of the first dimension spec., if any. - * @type string - */ - firstDimensionName: function(){ - var dt = this.firstDimensionType(); - return dt && dt.name; - }, - - /** - * Obtains the dimension value type of the first dimension spec., if any. - * @type string - */ - firstDimensionValueType: function(){ - var dt = this.firstDimensionType(); - return dt && dt.valueType; - }, - - /** - * Indicates if the grouping has no levels. - * @type boolean - */ - isNull: function(){ - return !this.levels.length; - }, - - /** - * Obtains a version of this grouping specification - * that conforms to the specified arguments. - * - * @param {string} [keyArgs.flatteningMode] The desired flatening mode. - * Supports the value 'singleLevel' as a way to signify the same as - * what the method {@link #singleLevelGrouping} does. - * - * @param {boolean} [keyArgs.reverse=false] Indicates that each dimension's order should be reversed. - * @type pvc.data.GroupingSpec - */ - ensure: function(keyArgs){ - var grouping = this, - flatteningMode = def.get(keyArgs, 'flatteningMode'); - - if(flatteningMode){ - if(flatteningMode === 'singleLevel'){ - // Supports reverse - return grouping.singleLevelGrouping(keyArgs); - } - - var flattenRootLabel = def.get(keyArgs, 'flattenRootLabel') || ''; - if(this.flatteningMode !== flatteningMode || (this.flattenRootLabel !== flattenRootLabel)){ - grouping = new pvc.data.GroupingSpec(grouping.levels, grouping.type, { - flatteningMode: flatteningMode, - flattenRootLabel: flattenRootLabel - }); - } - } - - if (def.get(keyArgs, 'reverse', false)){ - grouping = grouping.reversed(); - } - - return grouping; - }, - - /** - * Obtains a single-level version of this grouping specification. - * - *

- * If this grouping specification is itself single-level, - * then it is returned. - *

- * - * @param {object} [keyArgs] Keyword arguments - * @param {boolean} [keyArgs.reverse=false] Indicates that each dimension's order should be reversed. - * @type pvc.data.GroupingSpec - */ - singleLevelGrouping: function(keyArgs){ - var reverse = !!def.get(keyArgs, 'reverse', false); - if(this.isSingleLevel && !reverse) { - return this; - } - - /*jshint expr:true */ - this._singleLevelGrouping || (this._singleLevelGrouping = {}); - - var singleLevel = this._singleLevelGrouping[reverse]; - if(!singleLevel) { - var dimSpecs = this.dimensions() - .select(function(dimSpec){ - return reverse ? - new pvc.data.GroupingDimensionSpec(dimSpec.name, !dimSpec.reverse, dimSpec.type.complexType) : - dimSpec; - }); - - var levelSpec = new pvc.data.GroupingLevelSpec(dimSpecs, this.type); - - singleLevel = new pvc.data.GroupingSpec([levelSpec], this.type, {flatteningMode: this.flatteningMode}); - - this._singleLevelGrouping[reverse] = singleLevel; - } - - return singleLevel; - }, - - /** - * Obtains a reversed version of this grouping specification. - * - * @type pvc.data.GroupingSpec - */ - reversed: function(){ - var reverseGrouping = this._reverseGrouping; - if(!reverseGrouping) { - - var levelSpecs = def.query(this.levels) - .select(function(levelSpec){ - var dimSpecs = def.query(levelSpec.dimensions) - .select(function(dimSpec){ - return new pvc.data.GroupingDimensionSpec(dimSpec.name, !dimSpec.reverse, dimSpec.type.complexType); - }); - - return new pvc.data.GroupingLevelSpec(dimSpecs, this.type); - }); - - reverseGrouping = new pvc.data.GroupingSpec(levelSpecs, this.type, {flatteningMode: this.flatteningMode}); - - this._reverseGrouping = reverseGrouping; - } - - return reverseGrouping; - }, - - toString: function(){ - return def.query(this.levels) - .select(function(level){ return '' + level; }) - .array() - .join(', '); - } -}); - -def.type('pvc.data.GroupingLevelSpec') -.init(function(dimSpecs, type){ - var ids = []; - var dimNames = []; - - this.dimensions = def.query(dimSpecs) - .select(function(dimSpec){ - ids.push(dimSpec.id); - dimNames.push(dimSpec.name); - return dimSpec; - }) - .array(); - - this._dimNames = dimNames; - - this.dimensionsInDefOrder = this.dimensions.slice(0); - if(type){ - this._sortDimensions(type); - } - - this.id = ids.join(','); - this.depth = this.dimensions.length; - - var me = this; - this.comparer = function(a, b){ return me.compare(a, b); }; -}) -.add( /** @lends pvc.data.GroupingLevelSpec */{ - _sortDimensions: function(type){ - type.sortDimensionNames( - this.dimensionsInDefOrder, - function(d){ return d.name; }); - }, - - _setAccDimNames: function(accDimNames){ - this._accDimNames = accDimNames; - }, - - accDimensionNames: function(){ - return this._accDimNames; - }, - - dimensionNames: function(){ - return this._dimNames; - }, - - bind: function(type){ - this._sortDimensions(type); - - this.dimensions.forEach(function(dimSpec){ dimSpec.bind(type); }); - }, - - compare: function(a, b){ - for(var i = 0, D = this.depth ; i < D ; i++) { - var result = this.dimensions[i].compareDatums(a, b); - if(result !== 0) { - return result; - } - } - - return 0; - }, - - key: function(datum){ - var key = ''; - var atoms = {}; - var datoms = datum.atoms; - var dimNames = this._dimNames; - var keySep = datum.owner.keySep; - - // This builds a key compatible with that of pvc.data.Complex#key - for(var i = 0, D = this.depth ; i < D ; i++) { - var dimName = dimNames[i]; - var atom = datoms[dimName]; - atoms[dimName] = atom; - if(!i){ - key = atom.key; - } else { - key += keySep + atom.key; - } - } - - return {key: key, atoms: atoms, dimNames: dimNames}; - }, - - toString: function(){ - return def.query(this.dimensions) - .select(function(dimSpec){ return '' + dimSpec; }) - .array() - .join('|'); - } -}); - -def.type('pvc.data.GroupingDimensionSpec') -.init(function(name, reverse, type){ - this.name = name; - this.reverse = !!reverse; - this.id = this.name + ":" + (this.reverse ? '0' : '1'); - if(type){ - this.bind(type); - } -}) -.add( /** @lends pvc.data.GroupingDimensionSpec */ { - type: null, - comparer: null, - - /** - * Late binds a dimension specification to a complex type. - * @param {pvc.data.ComplexType} type A complex type. - */ - bind: function(type){ - /*jshint expr:true */ - type || def.fail.argumentRequired('type'); - - this.type = type.dimensions(this.name); - this.comparer = this.type.atomComparer(this.reverse); - }, - - compareDatums: function(a, b){ - //if(this.type.isComparable) { - var result = this.comparer(a.atoms[this.name], b.atoms[this.name]); - if(result !== 0) { - return result; - } - return 0; - //} - - // Use datum source order - //return this.reverse ? (b.id - a.id) : (a.id - b.id); - }, - - toString: function(){ - return this.name + (this.reverse ? ' desc' : ''); - } -}); - -/** - * Parses a grouping specification string. - * - * @param {string|string[]} [specText] The grouping specification text, - * or array of grouping specification level text. - * When unspecified, a null grouping is returned. - * - *

- * An example: - *

- *
- * "series1 asc, series2 desc, category"
- * 
- *

- * The following will group all the 'series' in one level and the 'category' in another: - *

- *
- * "series1 asc|series2 desc, category"
- * 
- * - * @param {pvc.data.ComplexType} [type] A complex type against which to resolve dimension names. - * - * @type pvc.data.GroupingSpec - */ -pvc.data.GroupingSpec.parse = function(specText, type){ - if(!specText){ - return new pvc.data.GroupingSpec(null, type); - } - - var levels; - if(def.array.is(specText)) { - levels = specText; - } else if(def.string.is(specText)) { - levels = specText.split(/\s*,\s*/); - } - - var levelSpecs = def.query(levels) - .select(function(levelText){ - var dimSpecs = groupSpec_parseGroupingLevel(levelText, type); - return new pvc.data.GroupingLevelSpec(dimSpecs, type); - }); - - return new pvc.data.GroupingSpec(levelSpecs, type); -}; - -var groupSpec_matchDimSpec = /^\s*(.+?)(?:\s+(asc|desc))?\s*$/i; - -/** - * @private - * @static - */ -function groupSpec_parseGroupingLevel(groupLevelText, type) { - /*jshint expr:true */ - def.string.is(groupLevelText) || def.fail.argumentInvalid('groupLevelText', "Invalid grouping specification."); - - return def.query(groupLevelText.split(/\s*\|\s*/)) - .where(def.truthy) - .select(function(dimSpecText){ - var match = groupSpec_matchDimSpec.exec(dimSpecText) || - def.fail.argumentInvalid('groupLevelText', "Invalid grouping level syntax '{0}'.", [dimSpecText]), - name = match[1], - order = (match[2] || '').toLowerCase(), - reverse = order === 'desc'; - - return new pvc.data.GroupingDimensionSpec(name, reverse, type); - }); -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/LinearInterpolationOper.js b/pacotes/ccc2/pvc/data/LinearInterpolationOper.js deleted file mode 100755 index 9062bcf..0000000 --- a/pacotes/ccc2/pvc/data/LinearInterpolationOper.js +++ /dev/null @@ -1,167 +0,0 @@ -def -.type('pvc.data.LinearInterpolationOper') -.init(function(allPartsData, data, catRole, serRole, valRole, stretchEnds){ - this._newDatums = []; - - this._data = data; - - var allCatDataRoot = allPartsData.flattenBy(catRole, {ignoreNulls: false}); - var allCatDatas = allCatDataRoot._children; - - var serDatas1 = this._serDatas1 = serRole.isBound() ? - data.flattenBy(serRole).children().array() : - [null]; // null series - - this._isCatDiscrete = catRole.grouping.isDiscrete(); - this._firstCatDim = !this._isCatDiscrete ? data.owner.dimensions(catRole.firstDimensionName()) : null; - this._stretchEnds = stretchEnds; - var valDim = this._valDim = data.owner.dimensions(valRole.firstDimensionName()); - - var visibleKeyArgs = {visible: true, zeroIfNone: false}; - - this._catInfos = allCatDatas.map(function(allCatData, catIndex){ - - var catData = data._childrenByKey[allCatData.key]; - - var catInfo = { - data: catData || allCatData, // may be null? - value: allCatData.value, - isInterpolated: false, - serInfos: null, - index: catIndex - }; - - catInfo.serInfos = - serDatas1 - .map(function(serData1){ - var group = catData; - if(group && serData1){ - group = group._childrenByKey[serData1.key]; - } - - var value = group ? - group.dimensions(valDim.name) - .sum(visibleKeyArgs) : - null; - - return { - data: serData1, - group: group, - value: value, - isNull: value == null, - catInfo: catInfo - }; - }, this); - - return catInfo; - }); - - this._serCount = serDatas1.length; - this._serStates = - def - .range(0, this._serCount) - .select(function(serIndex){ - return new pvc.data.LinearInterpolationOperSeriesState(this, serIndex); - }, this) - .array() - ; - - // Determine the sort order of the continuous base categories - // Categories assumed sorted. -// if(!this._isCatDiscrete && catDatas.length >= 2){ -// if((+catDatas[1].value) >= (+catDatas[0].value)){ -// this._comparer = def.compare; -// } else { -// this._comparer = def.compareReverse; -// } -// } -}) -.add({ - interpolate: function(){ - var catInfo; - while((catInfo = this._catInfos.shift())){ - catInfo.serInfos.forEach(this._visitSeries, this); - } - - // Add datums created during interpolation - var newDatums = this._newDatums; - if(newDatums.length){ - this._data.owner.add(newDatums); - } - }, - - _visitSeries: function(catSerInfo, serIndex){ - this._serStates[serIndex].visit(catSerInfo); - }, - - nextUnprocessedNonNullCategOfSeries: function(serIndex){ - // NOTE: while interpolating, - // only catInfos remaining to be processed - // remain in the _catInfos array (see {@link #interpolate}). - // As such, this finds the "next" (unprocessed) - // non-null cat. info. - var catIndex = 0, - catCount = this._catInfos.length; - - while(catIndex < catCount){ - var catInfo = this._catInfos[catIndex++]; - //if(!catInfo.isInterpolated){ - var catSerInfo = catInfo.serInfos[serIndex]; - if(!catSerInfo.isNull){ - return catSerInfo; - } - //} - } - } - - // NOTE: This was only needed when selection needed to - // divide in half between the last and next. -// _setCategory: function(catValue){ -// /*jshint expr:true */ -// !this._isCatDiscrete || def.assert("Only for continuous base."); -// -// // Insert sort into this._catInfos -// -// // catValue may be a new dimension value -// var catAtom = this._firstCatDim.intern(catValue, /* isVirtual */ true); -// -// catValue = catAtom.value; // now may be a Date object... -// -// // Check if and where to insert -// var index = -// def -// .array -// .binarySearch( -// this._catInfos, -// +catValue, -// this._comparer, -// function(catInfo){ return +catInfo.value; }); -// -// if(index < 0){ -// // New category -// // Insert at the two's complement of index -// var catInfo = { -// atom: catAtom, -// value: catValue, -// label: this._firstCatDim.format(catValue), -// isInterpolated: true -// }; -// -// catInfo.serInfos = -// def -// .range(0, this._serCount) -// .select(function(serScene, serIndex){ -// return { -// value: null, -// isNull: true, -// catInfo: catInfo -// }; -// }) -// .array(); -// -// this._catInfos.splice(~index, 0, catInfo); -// } -// -// return index; -// } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/LinearInterpolationOperSeriesState.js b/pacotes/ccc2/pvc/data/LinearInterpolationOperSeriesState.js deleted file mode 100755 index 4122183..0000000 --- a/pacotes/ccc2/pvc/data/LinearInterpolationOperSeriesState.js +++ /dev/null @@ -1,176 +0,0 @@ -def -.type('pvc.data.LinearInterpolationOperSeriesState') -.init(function(interpolation, serIndex){ - this.interpolation = interpolation; - this.index = serIndex; - - this._lastNonNull(null); -}) -.add({ - visit: function(catSeriesInfo){ - if(catSeriesInfo.isNull){ - this._interpolate(catSeriesInfo); - } else { - this._lastNonNull(catSeriesInfo); - } - }, - - _lastNonNull: function(catSerInfo){ - if(arguments.length){ - this.__lastNonNull = catSerInfo; // Last non-null - this.__nextNonNull = undefined; - } - - return this.__lastNonNull; - }, - - _nextNonNull: function(){ - return this.__nextNonNull; - }, - - _initInterpData: function(){ - // When a null category is found, - // and it is the first category, or it is right after a non-null category, - // the prop. __nextNonNull will have the value undefined - // (because _nextNonNull is reset to undefined every time that __lastNonNull is set). - // - // Then, the __nextNonNull category is determined, - // by looking ahead of the current (null) category - // (see {@link Interpolation#nextUnprocessedNonNullCategOfSeries}). - // - // If both a last and a next exist, - // the slope of the line connecting these is determined. - // - // The next processed category, if null, will not - // pass the test this.__nextNonNull !== undefined, - // guaranteeing that this initialization is only performed - // once for each series "segment" of null dots that is - // surrounded by non-null dots. - - // The start of a new segment? - if(this.__nextNonNull !== undefined){ - return; - } - - // Will be null if the series starts - // with null categories: - // S: 0 - 0 - x - var last = this.__lastNonNull; - - // Make sure not to store undefined to distinguish from uninitialized. - // When "last" is null, a non-null "next" is used in - // {@link #_interpolate } to "extend" the beginning of the series. - var next = this.__nextNonNull = - this.interpolation - .nextUnprocessedNonNullCategOfSeries(this.index) || - null; - - if(next && last){ - var fromValue = last.value; - var toValue = next.value; - var deltaValue = toValue - fromValue; - - if(this.interpolation._isCatDiscrete){ - var stepCount = next.catInfo.index - last.catInfo.index; - /*jshint expr:true */ - (stepCount >= 2) || def.assert("Must have at least one interpolation point."); - - this._stepValue = deltaValue / stepCount; - this._middleIndex = ~~(stepCount / 2); // Math.floor <=> ~~ - - var dotCount = (stepCount - 1); - this._isOdd = (dotCount % 2) > 0; - } else { - var fromCat = +last.catInfo.value; - var toCat = +next.catInfo.value; - var deltaCat = toCat - fromCat; - - this._steep = deltaValue / deltaCat; // should not be infinite, cause categories are different - - this._middleCat = (toCat + fromCat) / 2; - - // NOTE: This was only needed when selection needed to - // divide in half between the last and next. - // (Maybe) add a category - //this.interpolation._setCategory(this._middleCat); - } - } - }, - - _interpolate: function(catSerInfo){ - this._initInterpData(); - - var next = this.__nextNonNull; - var last = this.__lastNonNull; - var one = next || last; - if(!one){ - return; - } - - var value, group/*, isInterpolatedMiddle*/; - var interpolation = this.interpolation; - var catInfo = catSerInfo.catInfo; - - if(next && last){ - if(interpolation._isCatDiscrete){ - var groupIndex = (catInfo.index - last.catInfo.index); - value = last.value + this._stepValue * groupIndex; - - if(this._isOdd){ - group = groupIndex < this._middleIndex ? last.group : next.group; - //isInterpolatedMiddle = groupIndex === this._middleIndex; - } else { - group = groupIndex <= this._middleIndex ? last.group : next.group; - //isInterpolatedMiddle = false; - } - - } else { - var cat = +catInfo.value; - var lastCat = +last.catInfo.value; - - value = last.value + this._steep * (cat - lastCat); - group = cat < this._middleCat ? last.group : next.group; - //isInterpolatedMiddle = cat === this._middleCat; - } - } else { - // Only "stretch" ends on stacked visualization - if(!interpolation._stretchEnds) { - return; - } - - value = one.value; - group = one.group; - //isInterpolatedMiddle = false; - } - - // ----------- - - // Multi, series, ... atoms, other measures besides valDim. - var atoms = Object.create(group._datums[0].atoms); - - // Category atoms - //if(interpolation._isCatDiscrete || !catInfo.isInterpolated){ - def.copyOwn(atoms, catInfo.data.atoms); -// } else { -// // cat is a new category value -// var catAtom = catInfo.atom; -// -// atoms[catAtom.dimension.name] = catAtom; -// } - - // Value atom - var valueAtom = interpolation._valDim.intern(value, /* isVirtual */ true); - atoms[valueAtom.dimension.name] = valueAtom; - - // Create datum with collected atoms - var newDatum = new pvc.data.Datum(group.owner, atoms); - - newDatum.isVirtual = true; - newDatum.isInterpolated = true; - newDatum.interpolation = 'linear'; - - //newDatum.isInterpolatedMiddle = isInterpolatedMiddle; - - interpolation._newDatums.push(newDatum); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/ZeroInterpolationOper.js b/pacotes/ccc2/pvc/data/ZeroInterpolationOper.js deleted file mode 100755 index 6cb60a7..0000000 --- a/pacotes/ccc2/pvc/data/ZeroInterpolationOper.js +++ /dev/null @@ -1,99 +0,0 @@ -def -.type('pvc.data.ZeroInterpolationOper') -.init(function(allPartsData, data, catRole, serRole, valRole, stretchEnds){ - this._newDatums = []; - - this._data = data; - - var allCatDataRoot = allPartsData.flattenBy(catRole, {ignoreNulls: false}); - var allCatDatas = allCatDataRoot._children; - - var serDatas1 = this._serDatas1 = serRole.isBound() ? - data.flattenBy(serRole).children().array() : - [null]; // null series - - this._isCatDiscrete = catRole.grouping.isDiscrete(); - this._firstCatDim = !this._isCatDiscrete ? data.owner.dimensions(catRole.firstDimensionName()) : null; - this._stretchEnds = stretchEnds; - var valDim = this._valDim = data.owner.dimensions(valRole.firstDimensionName()); - - var visibleKeyArgs = {visible: true, zeroIfNone: false}; - - this._catInfos = allCatDatas.map(function(allCatData, catIndex){ - - var catData = data._childrenByKey[allCatData.key]; - - var catInfo = { - data: catData || allCatData, - value: allCatData.value, - isInterpolated: false, - serInfos: null, - index: catIndex - }; - - catInfo.serInfos = - serDatas1 - .map(function(serData1){ - var group = catData; - if(group && serData1){ - group = group._childrenByKey[serData1.key]; - } - - var value = group ? - group.dimensions(valDim.name) - .sum(visibleKeyArgs) : - null; - - return { - data: serData1, - group: group, - value: value, - isNull: value == null, - catInfo: catInfo - }; - }, this); - - return catInfo; - }); - - this._serCount = serDatas1.length; - this._serStates = - def - .range(0, this._serCount) - .select(function(serIndex){ - return new pvc.data.ZeroInterpolationOperSeriesState(this, serIndex); - }, this) - .array() - ; -}) -.add({ - interpolate: function(){ - var catInfo; - while((catInfo = this._catInfos.shift())){ - catInfo.serInfos.forEach(this._visitSeries, this); - } - - // Add datums created during interpolation - var newDatums = this._newDatums; - if(newDatums.length){ - this._data.owner.add(newDatums); - } - }, - - _visitSeries: function(catSerInfo, serIndex){ - this._serStates[serIndex].visit(catSerInfo); - }, - - nextUnprocessedNonNullCategOfSeries: function(serIndex){ - var catIndex = 0, - catCount = this._catInfos.length; - - while(catIndex < catCount){ - var catInfo = this._catInfos[catIndex++]; - var catSerInfo = catInfo.serInfos[serIndex]; - if(!catSerInfo.isNull){ - return catSerInfo; - } - } - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/ZeroInterpolationOperSeriesState.js b/pacotes/ccc2/pvc/data/ZeroInterpolationOperSeriesState.js deleted file mode 100755 index a347880..0000000 --- a/pacotes/ccc2/pvc/data/ZeroInterpolationOperSeriesState.js +++ /dev/null @@ -1,124 +0,0 @@ -def -.type('pvc.data.ZeroInterpolationOperSeriesState') -.init(function(interpolation, serIndex){ - this.interpolation = interpolation; - this.index = serIndex; - - this._lastNonNull(null); -}) -.add({ - visit: function(catSeriesInfo){ - if(catSeriesInfo.isNull){ - this._interpolate(catSeriesInfo); - } else { - this._lastNonNull(catSeriesInfo); - } - }, - - _lastNonNull: function(catSerInfo){ - if(arguments.length){ - this.__lastNonNull = catSerInfo; // Last non-null - this.__nextNonNull = undefined; - } - - return this.__lastNonNull; - }, - - _nextNonNull: function(){ - return this.__nextNonNull; - }, - - _initInterpData: function(){ - // The start of a new segment? - if(this.__nextNonNull !== undefined){ - return; - } - - var last = this.__lastNonNull; - var next = this.__nextNonNull = - this.interpolation - .nextUnprocessedNonNullCategOfSeries(this.index) || - null; - - if(next && last){ - var fromValue = last.value; - var toValue = next.value; - var deltaValue = toValue - fromValue; - - if(this.interpolation._isCatDiscrete){ - var stepCount = next.catInfo.index - last.catInfo.index; - /*jshint expr:true */ - (stepCount >= 2) || def.assert("Must have at least one interpolation point."); - - this._middleIndex = ~~(stepCount / 2); // Math.floor <=> ~~ - - var dotCount = (stepCount - 1); - this._isOdd = (dotCount % 2) > 0; - } else { - var fromCat = +last.catInfo.value; - var toCat = +next.catInfo.value; - this._middleCat = (toCat + fromCat) / 2; - } - } - }, - - _interpolate: function(catSerInfo){ - this._initInterpData(); - - var next = this.__nextNonNull; - var last = this.__lastNonNull; - var one = next || last; - if(!one){ - return; - } - - var group; - var interpolation = this.interpolation; - var catInfo = catSerInfo.catInfo; - - if(next && last){ - if(interpolation._isCatDiscrete){ - var groupIndex = (catInfo.index - last.catInfo.index); - if(this._isOdd){ - group = groupIndex < this._middleIndex ? last.group : next.group; - } else { - group = groupIndex <= this._middleIndex ? last.group : next.group; - } - - } else { - var cat = +catInfo.value; - group = cat < this._middleCat ? last.group : next.group; - } - } else { - // Only "stretch" ends on stacked visualization - if(!interpolation._stretchEnds) { - return; - } - - group = one.group; - } - - // ----------- - - // Multi, series, ... atoms, other measures besides valDim. - var atoms = Object.create(group._datums[0].atoms); - - // Category atoms - def.copyOwn(atoms, catInfo.data.atoms); - - // Value atom - var zeroAtom = interpolation._zeroAtom || - (interpolation._zeroAtom = - interpolation._valDim.intern(0, /* isVirtual */ true)); - - atoms[zeroAtom.dimension.name] = zeroAtom; - - // Create datum with collected atoms - var newDatum = new pvc.data.Datum(group.owner, atoms); - newDatum.isVirtual = true; - newDatum.isInterpolated = true; - newDatum.interpolation = 'zero'; - - interpolation._newDatums.push(newDatum); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/_data.js b/pacotes/ccc2/pvc/data/_data.js deleted file mode 100755 index a5486a8..0000000 --- a/pacotes/ccc2/pvc/data/_data.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Namespace with data related classes. - * @name pvc.data - * @namespace - */ - -/** - * @name NoDataException - * @class An error thrown when a chart has no data. - */ -def.global.NoDataException = function(){}; - - -pvc.data = { - visibleKeyArgs: {visible: true} -}; - -/** - * Disposes a list of child objects. - * - * @name pvc.data._disposeChildList - * - * @param {Array} list The list with children to dispose. - * @param {string} [parentProp] The child's parent property to reset. - * - * @static - * @private - */ -function data_disposeChildList(list, parentProp) { - if(list){ - list.forEach(function(child){ - if(parentProp) { - child[parentProp] = null; // HACK: to avoid child removing itself from its parent (this) - } - - child.dispose(); - }); - - list.length = 0; - } -} - -/** - * Adds a child object. - * - * @name pvc.data._addColChild - * - * @param {object} parent The parent. - * @param {string} childrenProp A parent's children array property. - * @param {object} child The child to add. - * @param {string} parentProp The child's parent property to set. - * @param {number} [index=null] The index at which to insert the child. - * - * @static - * @private - */ -function data_addColChild(parent, childrenProp, child, parentProp, index) { - // - /*jshint expr:true */ - (child && !child[parentProp]) || def.assert("Must not have a '" + parentProp + "'."); - // - - child[parentProp] = parent; - - var col = (parent[childrenProp] || (parent[childrenProp] = [])); - if(index == null || index >= col.length){ - col.push(child); - } else { - col.splice(index, 0, child); - } -} - -/** - * Removes a child object. - * - * @name pvc.data._removeColChild - * - * @param {object} parent The parent. - * @param {string} childrenProp A parent's children array property. - * @param {object} child The child to remove. - * @param {string} parentProp The child's parent property to reset. - * - * @static - * @private - */ -function data_removeColChild(parent, childrenProp, child, parentProp) { - // - /*jshint expr:true */ - (child && (!child[parentProp] || child[parentProp] === parent)) || def.assert("Not a child"); - // - - var children = parent[childrenProp]; - if(children) { - var index = children.indexOf(child); - if(index >= 0){ - def.array.removeAt(children, index); - } - } - - child[parentProp] = null; -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/meta/ComplexType.js b/pacotes/ccc2/pvc/data/meta/ComplexType.js deleted file mode 100755 index adbb1c5..0000000 --- a/pacotes/ccc2/pvc/data/meta/ComplexType.js +++ /dev/null @@ -1,442 +0,0 @@ -/** - * Initializes a complex type instance. - * - * @name pvc.data.ComplexType - * - * @class A complex type is, essentially, a named set of dimension types. - * - * @constructor - * - * @param {object} [dimTypeSpecs] - * A map of dimension names to dimension type constructor's keyword arguments. - * - * @see pvc.data.DimensionType - */ -def.type('pvc.data.ComplexType') -.init( -function(dimTypeSpecs){ - /** - * A map of the dimension types by name. - * - * @type object - * @private - */ - this._dims = {}; - - /** - * A list of the dimension types. - * - * @type pvc.data.DimensionType[] - * @private - */ - this._dimsList = []; - - /** - * A list of the dimension type names. - * - * @type string[] - * @private - */ - this._dimsNames = []; - - /** - * A list of the calculations - * ordered by calculation order. - * - * @type function[] - * @private - */ - this._calculations = []; - - /** - * A set of the names of - * dimension types being calculated. - * - * @type map(string boolean) - * @private - */ - this._calculatedDimNames = {}; - - /** - * An object with the dimension indexes by dimension name. - * - * @type object - * @private - */ - this._dimsIndexByName = null; - - /** - * An index of the dimension types by group name. - * - * @type object - * @private - */ - this._dimsByGroup = {}; - - /** - * An index of the dimension type names by group name. - * - * @type object - * @private - */ - this._dimsNamesByGroup = {}; - - if(dimTypeSpecs) { - for(var name in dimTypeSpecs){ - this.addDimension(name, dimTypeSpecs[name]); - } - } -}) -.add(/** @lends pvc.data.ComplexType# */{ - describe: function(){ - - var out = ["COMPLEX TYPE INFORMATION", pvc.logSeparator]; - - this._dimsList.forEach(function(type){ - var features = []; - - features.push(type.valueTypeName); - if(type.isComparable) { features.push("comparable"); } - if(!type.isDiscrete) { features.push("continuous"); } - if(type.isHidden) { features.push("hidden"); } - - out.push(" " + type.name + " (" + features.join(', ') + ")"); - }); - - //out.push(pvc.logSeparator); - - return out.join("\n"); - }, - - /** - * Obtains a dimension type given its name. - * - *

- * If no name is specified, - * a map with all dimension types indexed by name is returned. - * Do NOT modify this map. - *

- * - * @param {string} [name] The dimension type name. - * - * @param {object} [keyArgs] Keyword arguments - * @param {boolean} [keyArgs.assertExists=true] Indicates that an error is signaled - * if a dimension type with the specified name does not exist. - * - * @type pvc.data.DimensionType | pvc.data.DimensionType[] | null - */ - dimensions: function(name, keyArgs){ - if(name == null) { - return this._dims; - } - - var dimType = def.getOwn(this._dims, name, null); - if(!dimType && def.get(keyArgs, 'assertExists', true)) { - throw def.error.argumentInvalid('name', "Undefined dimension '{0}'", [name]); - } - - return dimType; - }, - - /** - * Obtains an array with all the dimension types. - * - *

- * Do NOT modify the returned array. - *

- * @type pvc.data.DimensionType[] - */ - dimensionsList: function(){ - return this._dimsList; - }, - - /** - * Obtains an array with all the calculated dimension types, - * in order of evaluation. - * - *

- * Do NOT modify the returned array. - *

- * @type pvc.data.DimensionType[] - */ - calculatedDimensionsList: function(){ - return this._calcDimsList; - }, - - /** - * Obtains an array with all the dimension type names. - * - *

- * Do NOT modify the returned array. - *

- * @type string[] - */ - dimensionsNames: function(){ - return this._dimsNames; - }, - - /** - * Obtains an array of the dimension types of a given group. - * - *

- * Do NOT modify the returned array. - *

- * - * @param {object} [keyArgs] Keyword arguments. - * @param {boolean} [keyArgs.assertExists=true] Indicates if an error is signaled when the specified group name is undefined. - * - * @type pvc.data.DimensionType[] - */ - groupDimensions: function(group, keyArgs){ - var dims = def.getOwn(this._dimsByGroup, group); - if(!dims && def.get(keyArgs, 'assertExists', true)) { - throw def.error.operationInvalid("There is no dimension type group with name '{0}'.", [group]); - } - - return dims; - }, - - /** - * Obtains an array of the dimension type names of a given group. - * - *

- * Do NOT modify the returned array. - *

- * - * @param {object} [keyArgs] Keyword arguments. - * @param {boolean} [keyArgs.assertExists=true] Indicates if an error is signaled when the specified group name is undefined. - * - * @type string[] - */ - groupDimensionsNames: function(group, keyArgs){ - var dimNames = def.getOwn(this._dimsNamesByGroup, group); - if(!dimNames && def.get(keyArgs, 'assertExists', true)) { - throw def.error.operationInvalid("There is no dimension type group with name '{0}'.", [group]); - } - - return dimNames; - }, - - /** - * Creates and adds to the complex type a new dimension type, - * given its name and specification. - * - * @param {string} name The name of the dimension type. - * @param {object} [dimTypeSpec] The dimension type specification. - * Essentially its a keyArgs object. - * See {@link pvc.data.DimensionType}'s keyArgs constructor - * to know about available arguments. - * - * @type {pvc.data.DimensionType} - */ - addDimension: function(name, dimTypeSpec){ - // - /*jshint expr:true */ - name || def.fail.argumentRequired('name'); - !def.hasOwn(this._dims, name) || def.fail.operationInvalid("A dimension type with name '{0}' is already defined.", [name]); - // - - var dimension = new pvc.data.DimensionType(this, name, dimTypeSpec); - this._dims[name] = dimension; - - this._dimsIndexByName = null; // reset - - var group = dimension.group; - var groupLevel; - if(group) { - var groupDims = def.getOwn(this._dimsByGroup, group), - groupDimsNames; - - if(!groupDims) { - groupDims = this._dimsByGroup[group] = []; - groupDimsNames = this._dimsNamesByGroup[group] = []; - } else { - groupDimsNames = this._dimsNamesByGroup[group]; - } - - // TODO: this sorting is lexicographic... - // TODO this should be unified with dimension.groupLevel... - groupLevel = def.array.insert(groupDimsNames, name, def.compare); - groupLevel = ~groupLevel; - def.array.insertAt(groupDims, groupLevel, dimension); - } - - var index; - var L = this._dimsList.length; - if(!group) { - index = L; - } else { - groupLevel = dimension.groupLevel; - - // Find the index of the last dimension of the same group - // or the one that has a higher level that this one - for(var i = 0 ; i < L ; i++){ - var dim = this._dimsList[i]; - if(dim.group === group){ - if(dim.groupLevel > groupLevel){ - // Before the current one - index = i; - break; - } - - // After the current one - index = i + 1; - } - } - - if(index == null){ - index = L; - } - } - - def.array.insertAt(this._dimsList, index, dimension); - def.array.insertAt(this._dimsNames, index, name); - - // calculated - if(dimension._calculate){ - index = def.array.binarySearch( - this._calcDimsList, - dimension._calculationOrder, - def.compare, - function(dimType){ return dimType._calculationOrder; }); - if(index >= 0){ - // Add after - index++; - } else { - // Add at the two's complement of index - index = ~index; - } - - def.array.insertAt(this._calcDimsList, index, dimension); - } - - this._isPctRoleDimTypeMap = null; - - return dimension; - }, - - addCalculation: function(calcSpec, dimsOptions){ - /*jshint expr:true */ - calcSpec || def.fail.argumentRequired('calcSpec'); - - var calculation = calcSpec.calculation || - def.fail.argumentRequired('calculations[i].calculation'); - - var dimNames = calcSpec.names; - if(typeof dimNames === 'string'){ - dimNames = dimNames.split(/\s*\,\s*/); - } else { - dimNames = def.array.as(dimNames); - } - - if(dimNames && dimNames.length){ - var calcDimNames = this._calculatedDimNames; - - dimNames.forEach(function(name){ - if(name){ - name = name.replace(/^\s*(.+?)\s*$/, "$1"); // trim - - !def.hasOwn(calcDimNames, name) || - def.fail.argumentInvalid('calculations[i].names', "Dimension name '{0}' is already being calculated.", [name]); - - // Dimension need to be created? - var dimType = this._dims[name]; - if(!dimType){ - var dimSpec = pvc.data.DimensionType.extendSpec(name, null, dimsOptions); - this.addDimension(name, dimSpec); - } - - calcDimNames[name] = true; - - dimType._toCalculated(); - } - }, this); - } - - this._calculations.push(calculation); - }, - - isCalculated: function(dimName){ - return def.hasOwn(this._calculatedDimNames, dimName); - }, - - _calculate: function(complex){ - var calcs = this._calculations; - if(calcs.length){ - var valuesByName = {}; - - calcs.forEach(function(calc){ - calc(complex, valuesByName); - }); - - return valuesByName; - } - }, - - /** - * Obtains a map of the dimension types, indexed by their name, - * that are playing a role such that {@link pvc.visual.Role#isPercent} is true. - * - * @type def.Map - */ - getPlayingPercentVisualRoleDimensionMap: function(){ - var map = this._isPctRoleDimTypeMap; - if(!map) { - map = this._isPctRoleDimTypeMap = new def.Map( - def.query(def.own(this._dims)) - .where(function(dimType){ return dimType.playingPercentVisualRole(); }) - .object({ - name: function(dimType) { return dimType.name; } - })); - } - - return map; - }, - - /** - * Sorts a specified dimension array in place, - * according to the definition order. - * - * @param {any[]} dims Array of dimension names. - * @param {function} [nameKey] Allows extracting the dimension name from - * each of the elements of the specified array. - * - * @type any[] - */ - sortDimensionNames: function(dims, nameKey){ - var dimsIndexByName = this._dimsIndexByName; - if(!dimsIndexByName){ - dimsIndexByName = - def - .query(this._dimsList) - .object({ - name: function(dim){ return dim.name; }, - value: function(dim, index){ return index; } - }); - this._dimsIndexByName = dimsIndexByName; - } - - dims.sort(function(da, db){ - return def.compare( - dimsIndexByName[nameKey ? nameKey(da) : da], - dimsIndexByName[nameKey ? nameKey(db) : db]); - - }); - - return dims; - } -}); - -/** - * Called by a dimension type to indicate that its assigned roles have changed. - * - * @name pvc.data.ComplexType#_dimensionRolesChanged - * @function - * @param {pvc.data.DimensionType} dimType The affected dimension type. - * @type undefined - * @private - * @internal - */ -function compType_dimensionRolesChanged(dimType) { - this._isPctRoleDimTypeMap = null; -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/meta/ComplexTypeProject.js b/pacotes/ccc2/pvc/data/meta/ComplexTypeProject.js deleted file mode 100755 index a50e791..0000000 --- a/pacotes/ccc2/pvc/data/meta/ComplexTypeProject.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Initializes a complex type project. - * - * @name pvc.data.ComplexType - * - * @class A complex type project is a work in progress set of dimension specifications. - */ -def.type('pvc.data.ComplexTypeProject') -.init( -function(dimGroupSpecs){ - this._dims = {}; - this._dimList = []; - this._dimGroupsDims = {}; - this._dimGroupSpecs = dimGroupSpecs || {}; - - this._calcList = []; -}) -.add(/** @lends pvc.data.ComplexTypeProject# */{ - _ensureDim: function(name){ - /*jshint expr:true*/ - name || def.fail.argumentInvalid('name', "Invalid dimension name '{0}'.", [name]); - - var info = def.getOwn(this._dims, name); - if(!info){ - info = this._dims[name] = this._createDim(name); - - this._dimList.push(info); - - var groupDimsNames = def.array.lazy(this._dimGroupsDims, info.groupName); - // TODO: this sorting is lexicographic but should be numeric - def.array.insert(groupDimsNames, name, def.compare); - } - - return info; - }, - - hasDim: function(name){ - return def.hasOwn(this._dims, name); - }, - - setDim: function(name, spec){ - var _ = this._ensureDim(name).spec; - if(spec){ - def.copy(_, spec); - } - - return this; - }, - - setDimDefaults: function(name, spec){ - def.setUDefaults(this._ensureDim(name).spec, spec); - return this; - }, - - _createDim: function(name, spec){ - var dimGroupName = pvc.data.DimensionType.dimensionGroupName(name); - var dimGroupSpec = this._dimGroupSpecs[dimGroupName]; - if(dimGroupSpec) { - spec = def.create(dimGroupSpec, spec /* Can be null */); - } - return { - name: name, - groupName: dimGroupName, - spec: spec || {} - }; - }, - - readDim: function(name){ - var info = this._ensureDim(name); - if(info.isRead){ - throw def.error.operationInvalid("Dimension '{0}' already is the target of a reader.", [name]); - } - if(info.isCalc){ - throw def.error.operationInvalid("Dimension '{0}' is being calculated, so it cannot be the target of a reader.", [name]); - } - - info.isRead = true; - }, - - calcDim: function(name){ - var info = this._ensureDim(name); - if(info.isCalc){ - throw def.error.operationInvalid("Dimension '{0}' already is being calculated.", [name]); - } - if(info.isRead){ - throw def.error.operationInvalid("Dimension '{0}' is the target of a reader, so it cannot be calculated.", [name]); - } - - info.isCalc = true; - }, - - isReadOrCalc: function(name){ - if(name){ - var info = def.getOwn(this._dims, name); - if(info){ - return info.isRead || info.isCalc; - } - } - - return false; - }, - - groupDimensionsNames: function(groupDimName){ - return this._dimGroupsDims[groupDimName]; - }, - - setCalc: function(calcSpec){ - /*jshint expr:true */ - calcSpec || def.fail.argumentRequired('calculations[i]'); - calcSpec.calculation || def.fail.argumentRequired('calculations[i].calculation'); - - var dimNames = calcSpec.names; - if(typeof dimNames === 'string'){ - dimNames = dimNames.split(/\s*\,\s*/); - } else { - dimNames = def.array.as(dimNames); - } - - if(dimNames && dimNames.length){ - dimNames.forEach(this.calcDim, this); - } - - this._calcList.push(calcSpec); - }, - - configureComplexType: function(complexType, translOptions){ - //var keyArgs = {assertExists: false}; - - this._dimList.forEach(function(dimInfo){ - var dimName = dimInfo.name; - //if(!complexType.dimensions(dimName, keyArgs)){ - var spec = dimInfo.spec; - - spec = pvc.data.DimensionType.extendSpec(dimName, spec, translOptions); - - complexType.addDimension(dimName, spec); - //} // TODO: else assert has not changed? - }); - - this._calcList.forEach(function(calcSpec){ - complexType.addCalculation(calcSpec); - }); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/meta/DimensionType.js b/pacotes/ccc2/pvc/data/meta/DimensionType.js deleted file mode 100755 index c4a9a26..0000000 --- a/pacotes/ccc2/pvc/data/meta/DimensionType.js +++ /dev/null @@ -1,576 +0,0 @@ - -/** - * Initializes a dimension type - * - * @name pvc.data.DimensionType - * - * @class A dimension type describes a dimension of a complex type. - *

- * Most of the held information is of - * intrinsic characteristics of the dimensions values. - * Yet, it also holds information - * related to a specific data translation usage. - *

- * - * @property {pvc.data.ComplexType} complexType - * The complex type that this dimension type belongs to. - * - * @property {string} name - * The name of this dimension type. - * The name of a dimension type is unique on its complex type. - * - * @property {string} label - * The label of this dimension type. - * The label should be unique on its complex type. - * - * @property {string} group The group that the dimension type belongs to. - *

- * The group name is taken to be the name of the dimension - * without any suffix numbers. - * So, if the name of a dimension type is 'series2', - * then its default group is 'series'. - *

- * - * @property {number} groupLevel The index within the group that the dimension type belongs to. - * - * @property {Function} valueType - * The type of the value of atoms belonging to dimensions of this type. - * It is a function that casts values to the represented type. - * - * The values null and undefined are never converted by this function. - * - * The function must be idempotent. - * - * @property {string} valueTypeName A description of the value type. - * - * @property {boolean} isDiscrete - * Indicates if the values of this dimension are - * to be considered discrete, - * as opposed to continuous, - * even if the value type is continuous. - * - * @property {boolean} isDiscreteValueType - * Indicates if the value type of the values of this dimension are discrete, - * as opposed to continuous. - * - * @property {boolean} isComparable - * Indicates if the values of this dimension can be compared. - * - * @property {boolean} isHidden Indicates if the dimension is - * hidden from the user, in places like a tooltip, for example, or in the legend. - * - * @property {def.Map} playedVisualRoles - * A map of {@link pvc.visual.Role} indexed by visual role name, of the visual roles currently being played by this dimension type. - * - * @constructor - * - * @param {pvc.data.ComplexType} complexType The complex type that this dimension belongs to. - * @param {string} name The name of the dimension type. - * - * @param {object} [keyArgs] Keyword arguments. - * @param {string} [keyArgs.label] The label of this dimension type. - * Defaults to the name of the dimension type. - * @param {function} [keyArgs.valueType=null] The type of the values of this dimension type. - *

- * The supported value types are: null (which really means any), {@link Boolean}, {@link Number}, {@link String}, {@link Date} and {@link Object}. - *

- * @param {boolean} [keyArgs.isHidden=false] Indicates if the dimension should - * be hidden from the user, in places like a tooltip, for example, or in the legend. - * @param {boolean} [keyArgs.isDiscrete] - * Indicates if the dimension - * is considered discrete. - * The default value depends on the value of {@link valueType}; - * it is true unless the {@link valueType} is Number or Date. - * - * @param {function} [keyArgs.converter] A function used in the translation phase - * to convert raw values into values of the dimension's value type. - * Its signature is: - *
- * function(rawValue : any) : valueType
- * 
- * - * @param {string} [keyArgs.rawFormat] A protovis format mask adequate to the specified value type. - * When specified and a converter is not specified, it is used to create a converter - * for the Date and Number value types. - * - * @param {function} [keyArgs.key] A function used in the translation phase - * to obtain the string key of each value. - * Its signature is: - *
- * function(value : valueType) : string
- * 
- *

- * Nully values have a fixed key of '', - * so to the function never receives a "nully" value argument. - * A consequence is that no other values can have an empty key. - *

- *

- * The default key is obtained by calling the value's {@link Object#toString} method. - *

- * - * @param {function} [keyArgs.formatter] A function used in the translation phase - * to format the values of this dimension type. - * Its signature is: - *
- * function(value : valueType, rawValue : any) : string
- * 
- *

- * Only a "nully" value should have an empty label. - *

- *

- * The label is not necessarily unique. - *

- *

- * The default format is the empty string for null values, - * or the result of calling the value's {@link Object#toString} method. - *

- * - * @param {string} [keyArgs.format] A protovis format mask adequate to the specified value type. - * When specified and a formatter is not specified, it is used to create a formatter - * for the Date and Number value types. - * - * @param {function} [keyArgs.comparer] - * Specifies a comparator function for the values of this dimension type. - * Its signature is: - *
- * function(valueA : valueType, valueB : valueType) : number
- * 
- * - * The default value depends on the value of {@link valueType}; - * it is {@link def.compare} when the {@link valueType} is Date, - * and null otherwise. - */ - -/** - * Cache of reverse order context-free value comparer function. - * - * @name pvc.data.DimensionType#_reverseComparer - * @field - * @type function - * @private - */ - -/** - * Cache of reverse order context-free atom comparer function. - * - * @name pvc.data.DimensionType#_reverseAtomComparer - * @field - * @type function - * @private - */ - -/** - * Cache of normal order context-free value comparer function. - * - * @name pvc.data.DimensionType#_directComparer - * @field - * @type function - * @private - */ - -/** - * Cache of normal order context-free atom comparer function. - * - * @name pvc.data.DimensionType#_directAtomComparer - * @field - * @type function - * @private - */ -def.type('pvc.data.DimensionType') -.init( -function(complexType, name, keyArgs){ - this.complexType = complexType; - this.name = name; - this.label = def.get(keyArgs, 'label') || pvc.buildTitleFromName(name); - - var groupAndLevel = pvc.splitIndexedId(name); - this.group = groupAndLevel[0]; - this.groupLevel = def.nullyTo(groupAndLevel[1], 0); - - if(this.label.indexOf('{') >= 0){ - this.label = def.format(this.label, [this.groupLevel+1]); - } - - this.playedVisualRoles = new def.Map(); - this.isHidden = !!def.get(keyArgs, 'isHidden'); - - var valueType = def.get(keyArgs, 'valueType') || null; - var valueTypeName = pvc.data.DimensionType.valueTypeName(valueType); - var cast = def.getOwn(pvc.data.DimensionType.cast, valueTypeName, null); - - this.valueType = valueType; - this.valueTypeName = valueTypeName; - this.cast = cast; - - this.isDiscreteValueType = (this.valueType !== Number && this.valueType !== Date); - this.isDiscrete = def.get(keyArgs, 'isDiscrete'); - if(this.isDiscrete == null){ - this.isDiscrete = this.isDiscreteValueType; - } else { - // Normalize the value - this.isDiscrete = !!this.isDiscrete; - if(!this.isDiscrete && this.isDiscreteValueType) { - throw def.error.argumentInvalid('isDiscrete', "The only supported continuous value types are Number and Date."); - } - } - - /** - * @private - * @internal - * @see pvc.data.Dimension#convert - */ - this._converter = def.get(keyArgs, 'converter') || null; - if(!this._converter) { - var rawFormat = def.get(keyArgs, 'rawFormat'); - if(rawFormat) { - /*jshint onecase:true */ - switch(this.valueType) { -// case Number: -// // TODO: receive extra format configuration arguments -// // this._converter = pv.Format.createParser(pv.Format.number().fractionDigits(0, 2)); -// break; - - case Date: - this._converter = pv.Format.createParser(pv.Format.date(rawFormat)); - break; - } - } - } - - /** - * @private - * @internal - * @see pvc.data.Dimension#key - */ - this._key = def.get(keyArgs, 'key') || null; - - /** @private */ - this._comparer = def.get(keyArgs, 'comparer'); - if(this._comparer === undefined){ // It is possible to prevent the default specifying null - switch(this.valueType){ - case Number: - case Date: - this._comparer = def.compare; - break; - - default: - this._comparer = null; - } - } - - this.isComparable = this._comparer != null; - - /** - * @private - * @internal - * @see pvc.data.Dimension#format - */ - this._formatter = def.get(keyArgs, 'formatter') || null; - if(!this._formatter) { - switch(this.valueType) { - case Number: - // TODO: receive extra format configuration arguments - this._formatter = pv.Format.createFormatter(pv.Format.number().fractionDigits(0, 2)); - break; - - case Date: - var format = def.get(keyArgs, 'format'); - if(!format){ - // Try to create one from raw format - // slightly modifying it to look like - // protovis' continuous date scale dynamic formats - format = def.get(keyArgs, 'rawFormat'); - if(format){ - format = format.replace(/-/g, "/"); - } - } - - if(!format){ - format = "%Y/%m/%d"; - } - - this._formatter = pv.Format.createFormatter(pv.Format.date(format)); - break; - } - } -}) -.add(/** @lends pvc.data.DimensionType# */{ - - isCalculated: false, - - /** - * Compares two values of the dimension's {@link #valueType}, in ascending order. - *

- * To compare two values in descending order multiply the result by -1. - *

- *

- * Values can be nully. - *

- * @param {any} a A value of the dimension's {@link #valueType}. - * @param {any} b A value of the dimension's {@link #valueType}. - * - * @returns {Number} - * A negative number if {@link a} is before {@link b}, - * a positive number if {@link a} is after {@link b}, - * and 0 if they are considered to have the same order. - */ - compare: function(a, b){ - if(a == null) { - if(b == null) { - return 0; - } - return -1; - } else if(b == null) { - return 1; - } - - return this._comparer.call(null, a, b); - }, - - /** - * Gets a context-free comparer function - * for values of the dimension's {@link #valueType} - * and for a specified order. - * - *

When the dimension type is not comparable, null is returned.

- * - * @param {boolean} [reverse=false] Indicates if the comparison order should be reversed. - * - * @type function - */ - comparer: function(reverse){ - if(!this.isComparable) { - return null; - } - - var me = this; - if(reverse){ - return this._reverseComparer || - (this._reverseComparer = function(a, b){ return me.compare(b, a); }); - } - - return this._directComparer || (this._directComparer = function(a, b){ return me.compare(a, b); }); - }, - - /** - * Gets a context-free atom comparer function, - * for a specified order. - * - * @param {boolean} [reverse=false] Indicates if the comparison order should be reversed. - * - * @type function - */ - atomComparer: function(reverse){ - if(reverse){ - return this._reverseAtomComparer || - (this._reverseAtomComparer = this._createReverseAtomComparer()); - } - - return this._directAtomComparer || - (this._directAtomComparer = this._createDirectAtomComparer()); - }, - - // Coercion to discrete upon the role binding (irreversible...) - _toDiscrete: function(){ - this.isDiscrete = true; - }, - - _toCalculated: function(){ - this.isCalculated = true; - }, - - _createReverseAtomComparer: function(){ - if(!this.isComparable){ - /*global atom_idComparerReverse:true */ - return atom_idComparerReverse; - } - - var me = this; - - function reverseAtomComparer(a, b){ - if(a === b) { return 0; } // Same atom - return me.compare(b.value, a.value); - } - - return reverseAtomComparer; - }, - - _createDirectAtomComparer: function(){ - if(!this.isComparable){ - /*global atom_idComparer:true */ - return atom_idComparer; - } - - var me = this; - - function directAtomComparer(a, b){ - if(a === b) { return 0; } // Same atom - return me.compare(a.value, b.value); - } - - return directAtomComparer; - }, - - /** - * Gets the dimension type's context-free formatter function, if one is defined, or null otherwise. - * @type function - */ - formatter: function(){ - return this._formatter; - }, - - /** - * Gets the dimension type's context-free converter function, if one is defined, or null otherwise. - * @type function - */ - converter: function(){ - return this._converter; - }, - - /** - * Obtains a value indicating if this dimension type plays any visual role - * such that {@link pvc.visual.Role#isPercent} is true. - * @type boolean - */ - playingPercentVisualRole: function(){ - return def.query(this.playedVisualRoles.values()) - .any(function(visualRole){ - return visualRole.isPercent; - }); - } -}); - -pvc.data.DimensionType.cast = { - 'Date': function(value) { - return value instanceof Date ? value : new Date(value); - }, - - 'Number': function(value) { - value = Number(value); - return isNaN(value) ? null : value; - }, - - 'String': String, - 'Boolean': Boolean, - 'Object': Object, - 'Any': null -}; - -/** - * Obtains the default group name for a given dimension name. - * - * @param {string} dimName The dimension name. - * - * @type string - */ -pvc.data.DimensionType.dimensionGroupName = function(dimName){ - return dimName.replace(/^(.*?)(\d*)$/, "$1"); -}; - -// TODO: Docs -pvc.data.DimensionType.valueTypeName = function(valueType){ - if(valueType == null){ - return "Any"; - } - - switch(valueType){ - case Boolean: return 'Boolean'; - case Number: return 'Number'; - case String: return 'String'; - case Object: return 'Object'; - case Date: return 'Date'; - default: throw def.error.argumentInvalid('valueType', "Invalid valueType function: '{0}'.", [valueType]); - } -}; - -/** - * Extends a dimension type specification with defaults based on - * group name and specified options. - * - * @param {object} [keyArgs] Keyword arguments. - * @param {function} [keyArgs.isCategoryTimeSeries=false] Indicates if category dimensions are to be considered time series. - * @param {string} [keyArgs.timeSeriesFormat] The parsing format to use to parse a Date dimension when the converter and rawFormat options are not specified. - * @param {function} [keyArgs.valueNumberFormatter] The formatter to use to parse a numeric dimension of the 'value' dimension group, when the formatter and format options are not specified. - * @param {object} [keyArgs.dimensionGroups] A map of dimension group names to dimension type specifications to be used as prototypes of corresponding dimensions. - * - * @returns {object} The extended dimension type specification. - */ -pvc.data.DimensionType.extendSpec = function(dimName, dimSpec, keyArgs){ - - var dimGroup = pvc.data.DimensionType.dimensionGroupName(dimName), - userDimGroupsSpec = def.get(keyArgs, 'dimensionGroups'); - - if(userDimGroupsSpec) { - var groupDimSpec = userDimGroupsSpec[dimGroup]; - if(groupDimSpec) { - dimSpec = def.create(groupDimSpec, dimSpec /* Can be null */); - } - } - - if(!dimSpec) { - dimSpec = {}; - } - - switch(dimGroup) { - case 'category': - var isCategoryTimeSeries = def.get(keyArgs, 'isCategoryTimeSeries', false); - if(isCategoryTimeSeries) { - if(dimSpec.valueType === undefined) { - dimSpec.valueType = Date; - } - } - break; - - case 'value': - if(dimSpec.valueType === undefined) { - dimSpec.valueType = Number; - } - - if(dimSpec.valueType === Number) { - if(dimSpec.formatter === undefined && - !dimSpec.format){ - dimSpec.formatter = def.get(keyArgs, 'valueNumberFormatter'); - } - } - break; - } - - if(dimSpec.converter === undefined && - dimSpec.valueType === Date && - !dimSpec.rawFormat) { - dimSpec.rawFormat = def.get(keyArgs, 'timeSeriesFormat'); - } - - return dimSpec; -}; - -/** - * Adds a visual role to the dimension type. - * - * @name pvc.data.DimensionType#_addVisualRole - * @function - * @param {pvc.visual.Role} visualRole The visual role. - * @type undefined - * @private - * @internal - */ -function dimType_addVisualRole(visualRole) { - this.playedVisualRoles.set(visualRole.name, visualRole); - /*global compType_dimensionRolesChanged:true */ - compType_dimensionRolesChanged.call(this.type, this); -} - -/** - * Removes a visual role from the dimension type. - * - * @name pvc.data.DimensionType#_removeVisualRole - * @function - * @param {pvc.visual.Role} visualRole The visual role. - * @type undefined - * @private - * @internal - */ -function dimType_removeVisualRole(visualRole) { - this.playedVisualRoles.rem(visualRole.name); - compType_dimensionRolesChanged.call(this.type, this); -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/translation/BoxplotChartTranslationOper.js b/pacotes/ccc2/pvc/data/translation/BoxplotChartTranslationOper.js deleted file mode 100755 index 526657c..0000000 --- a/pacotes/ccc2/pvc/data/translation/BoxplotChartTranslationOper.js +++ /dev/null @@ -1,44 +0,0 @@ - -/** - * @name pvc.data.BoxplotChartTranslationOper - * - * @class The translation mixin operation of the box plot chart. - * - *

- * The default box plot format is: - *

- *
- * +----------+----------+--------------+--------------+------------+-------------+
- * | 0        | 1        | 2            | 3            | 4          | 5           |
- * +----------+----------+--------------+--------------+------------+-------------+
- * | category | median   | lowerQuartil | upperQuartil | minimum    | maximum     |
- * +----------+----------+--------------+--------------+------------+-------------+
- * | any      | number   | number       | number       | number     | number      |
- * +----------+----------+--------------+--------------+------------+-------------+
- * 
- * - * @extends pvc.data.MatrixTranslationOper - */ -def.type('pvc.data.BoxplotChartTranslationOper') -.add(/** @lends pvc.data.BoxplotChartTranslationOper# */{ - /** - * @override - */ - _configureTypeCore: function(){ - var autoDimNames = []; - - var V = this.virtualItemSize(); - var C = V - this.M; - - this._getUnboundRoleDefaultDimNames('category', C, autoDimNames); - - pvc.BoxplotChart.measureRolesNames.forEach(function(roleName){ - this._getUnboundRoleDefaultDimNames(roleName, 1, autoDimNames); - }, this); - - autoDimNames.slice(0, this.freeVirtualItemSize()); - if(autoDimNames.length){ - this.defReader({names: autoDimNames}); - } - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/translation/CrosstabTranslationOper.js b/pacotes/ccc2/pvc/data/translation/CrosstabTranslationOper.js deleted file mode 100755 index e3823a2..0000000 --- a/pacotes/ccc2/pvc/data/translation/CrosstabTranslationOper.js +++ /dev/null @@ -1,741 +0,0 @@ - -/** - * @name pvc.data.CrosstabTranslationOper - * @class A translation from a matrix in crosstab format. - *

- * The default matrix-crosstab format is: - *

- *
- * +----------+----------+----------+
- * | -        | S1       | S2       | ... (taken from metadataItem.colName)
- * +==========+==========+==========+
- * | C1       | 12       | 45       |
- * | C2       | 11       | 99       |
- * | C3       | null     |  3       |
- * +----------+----------+----------+
- * 
- *

Legend:

- *
    - *
  • Ci — Category value i
  • - *
  • Sj — Series value j
  • - *
- * - * TODO: document crosstab options - * - * @extends pvc.data.MatrixTranslationOper - */ -def.type('pvc.data.CrosstabTranslationOper', pvc.data.MatrixTranslationOper) -.add(/** @lends pvc.data.CrosstabTranslationOper# */{ - /* LEGEND - * ====== - * - * Matrix Algebra - * -------------- - * - * j - * +---+ - * i | v | - * +---+ - * - * i - index of matrix line - * j - index of matrix column - * - * v - value at indexes i,j - * - * ---- - * - * line = matrix[i] - * value = line[j] - * - * - * Crosstab Algebra - * ---------------- - * - * CC - * +----+ - * RR | MM | - * +----+ - * - * RR = row space - * CC = column space - * MM = measure space - * - * ---- - * As a function - * - * cross-table: RR X CC -> MM - * - * ---- - * Dimension of spaces (called "depth" in the code to not confuse with Dimension) - * - * R = number of row components - * C = number of column components - * M = number of measure components - * - * ---- - * Instances / groups / members - * - * = = R-tuple of row values - * = = C-tuple of column values - * = = M-tuple of measure values - * - * r = index of row group component - * c = index of column group component - * m = index of measure group component - * - * ---- - * Extent of spaces - * - * RG = number of (distinct) row groups - * CG = number of (distinct) column groups - * MG = RG * CG - * - * rg = index of row group - * cg = index of column group - * - * - * - * Crosstab in a Matrix - * -------------------- - * - * Expand components into own columns: - * | <...RG...> | <=> | r1 | r2 | r3 | ... | rR | - * - * All component values joined with a separator character, ~, - * occupying only one column: - * | <~CG~> | <=> | "c1~c2~c3~...~cC" | - * - * ---- - * - * Format: "Measures in columns" (uniform) - * - * 0 R R+M R+M*(CG-1) R+M*CG - * o------------+------------+ ... +------------o (j - matrix column) - * - * 0 1 CG-1 CG - * o------------+ ... +------------o (cg - column group index) - * - * +------------+ ... +------------+ <-- this._colGroups - * X | <~CG~> | | <~CG~> | - * +------------+ +------------+ - * - * 0 o +------------+------------+ ... +------------+ <-- this._lines - * | | <...RG...> | <...MG...> | | <...MG...> | - * | | | <...MG...> | | <...MG...> | - * 1 + +------------+------------+ +------------+ - * ^ - * . | - * . m = cg % M - * . - * - * | - * RG o - * (i - matrix line) - * (rg - row group) - * - * i = rg - * j = R + M*cg - * - * Unfortunately, not all measures have to be specified in all column groups. - * When a measure in column group would have all rows with a null value, it can be omitted. - * - * Virtual Item Structure - * ---------------------- - * A relational view of the cross groups - * - * [<...CG...>, <...RG...>, <...MG...>] - * - * This order is chosen to match that of the relational translation. - * - * Virtual Item to Dimensions mapping - * ---------------------------------- - * - * A mapping from a virtual item to a list of atoms (of distinct dimensions) - * - * virtual-item --> atom[] - * - * A set of dimensions readers are called and - * each returns one or more atoms of distinct dimensions. - * - * * Each dimension has exactly one dimensions reader that reads its atoms. - * * One dimensions reader may read more than one dimension. - * * A dimensions reader always reads the same set of dimensions. - * - * * A dimension consumes data from zero or more virtual item components. - * * A virtual item component is consumed by zero or more dimensions. - * * A dimension may vary in which virtual item components it consumes, from atom to atom. - * - * virtual-item-component * <-> * dimension + <-> 1 dimensions reader - */ - - /** - * Obtains the number of fields of the virtual item. - * @type number - * @override - */ - virtualItemSize: function(){ - return this.R + this.C + this.M; - }, - - /** - * Performs the translation operation (override). - * @returns {def.Query} An enumerable of {@link map(string any)} - * @override - */ - _executeCore: function(){ - if(!this.metadata.length){ - return def.query(); - } - - var dimsReaders = this._getDimensionsReaders(); - - // ---------------- - // Virtual item - - var item = new Array(this.virtualItemSize()), - itemCrossGroupIndex = this._itemCrossGroupIndex, - me = this - ; - - // Updates VITEM - // . <- source = line[0..R] - // . <- source = colGroup[0..C] - function updateVItemCrossGroup(crossGroupId, source) { - // Start index of cross group in item - var itemIndex = itemCrossGroupIndex[crossGroupId], - sourceIndex = 0, - depth = me[crossGroupId]; - - while((depth--) > 0) { - item[itemIndex++] = source[sourceIndex++]; - } - } - - // . <- line[colGroupIndexes[0..M]] - function updateVItemMeasure(line, cg) { - // Start index of cross group in item - var itemIndex = itemCrossGroupIndex.M; - var cgIndexes = me._colGroupsIndexes[cg]; - var depth = me.M; - - for(var i = 0 ; i < depth ; i++){ - var lineIndex = cgIndexes[i]; - item[itemIndex++] = lineIndex != null ? line[lineIndex] : null; - } - } - - // ---------------- - - function expandLine(line/*, i*/){ - updateVItemCrossGroup('R', line); - - return def.query(this._colGroups) - .select(function(colGroup, cg){ - // Update ITEM - updateVItemCrossGroup('C', colGroup); - updateVItemMeasure(line, cg); - - // Naive approach... - // Call all readers every time - // Dimensions that consume rows and/or columns may be evaluated many times. - // So, it's very important that pvc.data.Dimension#intern is as fast as possible - // detecting already interned values. - return this._readItem(item, dimsReaders); - }, this); - } - - return def.query(this._lines) - .selectMany(expandLine, this); - }, - - _processMetadata: function(){ - - this.base(); - - this._separator = this.options.separator || '~'; - - /* Don't change source */ - var lines = pvc.cloneMatrix(this.source); - - this._lines = lines; - - /* Determine R, C and M */ - - // Default values - this.R = 1; - this.C = 1; - this.M = 1; - - this.measuresDirection = null; - - var colNames; - if(this.options.seriesInRows){ - colNames = this.metadata.map(function(d){ return d.colName; }); - } else if(this.options.compatVersion <= 1){ - colNames = this.metadata.map(function(d){ return {v: d.colName}; }); - } else { - colNames = this.metadata.map(function(d){ return {v: d.colName, f: d.colLabel }; }); - } - - // For each cross group, - // an array with the value types of each of its columns - // C|R|M -> [0|1, ...] - // 1 - continuous (number, date) - // 0 - discrete (anything else) - var itemCrossGroupTypes = this._itemCrossGroupTypes = { - /* - 'C': [], - 'R': [], - 'M': [] - */ - }; - - // -------------- - // * isMultiValued - // * measuresInColumns - // * measuresIndex, [measuresCount=1] - // * [categoriesCount = 1] - - // ~~~~ R* - - if(!this.options.isMultiValued) { - // | C - // ---|--- - // R* | M - - this.R = this._getCategoriesCount(); - - // C = 1 - // M = 1 - - this._colGroups = colNames.slice(this.R); - this._colGroupsIndexes = new Array(this._colGroups.length); - - // To Array - this._colGroups.forEach(function(colGroup, cg){ - this._colGroups[cg] = [colGroup]; - this._colGroupsIndexes[cg] = [this.R + cg]; // all the same - }, this); - - // R is set below - itemCrossGroupTypes.C = [0]; // 1 discrete column - itemCrossGroupTypes.M = [this._columnTypes[this.R]]; - } else { - /* MULTI-VALUED */ - - var measuresInColumns = def.get(this.options, 'measuresInColumns', true); - if(measuresInColumns || this.options.measuresIndex == null) { - - this.R = this._getCategoriesCount(); - - // First R columns are from row space - var encodedColGroups = colNames.slice(this.R); - - // Remaining are column and measure types - var L = encodedColGroups.length; - - // Any results in column direction... - if(L > 0) { - - if(!measuresInColumns) { - // ~~~~ C* M - - // | C* - // ---|---- - // R* | M - - this._colGroups = encodedColGroups; - this._colGroupsIndexes = []; - - // Split encoded column groups - this._colGroups.forEach(function(colGroup, cg){ - this._colGroups[cg] = this._splitEncodedColGroupCell(colGroup); - this._colGroupsIndexes[cg] = [this.R + cg]; // all the same - }, this); - - itemCrossGroupTypes.M = [this._columnTypes[this.R]]; - - } else { - // ~~~~ C* M* - - // | C*~M* - // ---|------ - // R* | M* - - this.measuresDirection = 'columns'; - - // Updates: - // _colGroups, - // _colGroupsIndexes and - // M - // _itemCrossGroupTypes.M - this._processEncodedColGroups(encodedColGroups); - } - - this.C = this._colGroups[0].length; // may be 0! - - itemCrossGroupTypes.C = def.array.create(this.C, 0); // C discrete columns - - } else { - this.C = this.M = 0; - itemCrossGroupTypes.M = itemCrossGroupTypes.C = []; - } - - } else { - // TODO: complete this - // TODO: itemCrossGroupTypes - - /* MEASURES IN ROWS */ - - this.measuresDirection = 'rows'; - - // C = 1 (could also be more if an option to make ~ on existed) - // R = 1 (could be more...) - // M >= 1 - - // The column index at which measure values (of each series) start - // is the number of row components - this.R = +this.options.measuresIndex; - - var measuresCount = this.options.measuresCount; - if (measuresCount == null) { - measuresCount = 1; - } - - // TODO: >= 1 check - this.M = measuresCount; - - // First R columns are from row space - // Next follows a non-relevant Measure title column - this._colGroups = colNames.slice(this.R + 1); - - // To Array of Cells - this._colGroups.forEach(function(colGroup, cg){ - this._colGroups[cg] = [colGroup]; - }, this); - } - } - - // First R columns are from row space - itemCrossGroupTypes.R = this._columnTypes.slice(0, this.R); - - // ---------------- - // The index at which the first component of - // each cross group is placed in virtual item - - var seriesInRows = this.options.seriesInRows; - - var itemGroupIndex = this._itemCrossGroupIndex = { - 'C': !seriesInRows ? 0 : this.R, - 'R': !seriesInRows ? this.C : 0, - 'M': this.C + this.R - }; - - var itemTypes = this._itemTypes = new Array(this.virtualItemSize()); // R + C + M - - def.eachOwn(itemGroupIndex, function(groupStartIndex, crossGroup){ - itemCrossGroupTypes[crossGroup] - .forEach(function(type, groupIndex){ - itemTypes[groupStartIndex + groupIndex] = type; - }); - }); - - // Logical view - - this._itemLogicalGroup = { - 'series': seriesInRows ? this.R : this.C, - 'category': seriesInRows ? this.C : this.R, - 'value': this.M - }; - - this._itemLogicalGroupIndex = { - 'series': 0, - 'category': this._itemLogicalGroup.series, - 'value': this.C + this.R - }; - - // ---------------- - - if(pvc.debug >= 3){ - pvc.log("Crosstab translator " + pvc.stringify({ - R: this.R, - C: this.C, - M: this.M - })); - } - }, - - _getCategoriesCount: function(){ - var R = this.options.categoriesCount; - if(R != null && (!isFinite(R) || R < 0)){ - R = null; - } - - if(R == null){ - // Number of consecutive discrete columns, from left - R = def - .query(this._columnTypes) - .whayl(function(type){ return type === 0; }) // 0 = discrete - .count(); - if(!R){ - // Having no R causes problems - // when categories are continuous - // (in MetricDots for example). - R = 1; - } - } - - return R; - }, - - _splitEncodedColGroupCell: function(colGroup){ - var values = colGroup.v; - var labels; - - if(values == null){ - values = []; - } else { - values = values.split(this._separator); - labels = colGroup.f; - if(labels){ - labels = labels.split(this._separator); - } - } - - return values.map(function(value, index){ - return { - v: value, - f: labels && labels[index] - }; - }); - }, - - /** - * Analyzes the array of encoded column groups. - *

- * Creates an array of column groups; - * where each element of the array is - * an array of the column values of the group (C values). - *

- *

- * In the process the number of encoded measures is determined, {@link #M}. - * In this respect, note that not all measures need to be supplied - * in every column group. - * When a measure is not present, that means that the value of the measure - * in every row is null. - *

- *

- * It is assumed that the order of measures in column groups is stable. - * So, if in one column group "measure 1" is before "measure 2", - * then it must be also the case in every other column group. - * This order is then used to place values in the virtual item. - *

- */ - _processEncodedColGroups: function(encodedColGroups){ - var L = encodedColGroups.length || def.assert("Must have columns"), - R = this.R, - colGroups = [], - currColGroup, - /* - * measureName -> { - * groupIndex: 0, // Global order of measures within a column group - * index: 0 // Index (i, below) of measure's first appearance - * } - * - */ - measuresInfo = {}, - measuresInfoList = [] - ; - - for(var i = 0 ; i < L ; i++){ - var colGroupCell = encodedColGroups[i]; - - var encColGroupValues = colGroupCell.v; - var encColGroupLabels = colGroupCell.f; - var sepIndex = encColGroupValues.lastIndexOf(this._separator); - - var meaName, colGroupValues, colGroupLabels; - - // MeasureName has precedence, - // so we may end up with no column group value (and C = 0). - if(sepIndex < 0){ - // C = 0 - meaName = encColGroupValues; - encColGroupValues = ''; - colGroupValues = []; - } else { - meaName = encColGroupValues.substring(sepIndex + 1); - encColGroupValues = encColGroupValues.substring(0, sepIndex); - colGroupValues = encColGroupValues.split(this._separator); - - if(encColGroupLabels != null){ - colGroupLabels = encColGroupLabels.split(this._separator); - colGroupLabels.pop(); // measure label - } - - /*jshint loopfunc:true */ - colGroupValues.forEach(function(value, index){ - var label = colGroupLabels && colGroupLabels[index]; - colGroupValues[index] = {v: value, f: label}; - }); - } - - // New column group? - if(!currColGroup || currColGroup.encValues !== encColGroupValues){ - currColGroup = { - startIndex: i, - encValues: encColGroupValues, - values: colGroupValues, - measureNames: [meaName] - }; - - colGroups.push(currColGroup); - } else { - currColGroup.measureNames.push(meaName); - } - - // Check the measure - var currMeaIndex = (i - currColGroup.startIndex), - meaInfo = def.getOwn(measuresInfo, meaName); - if(!meaInfo){ - measuresInfo[meaName] = meaInfo = { - name: meaName, - groupIndex: currMeaIndex, - index: i, - type: this._columnTypes[R + i] // Trust the type of the first column where the measure appears - }; - measuresInfoList.push(meaInfo); - } else if(currMeaIndex > meaInfo.groupIndex) { - meaInfo.groupIndex = currMeaIndex; - } - } - - // Sort measures - measuresInfoList.sort(function(meaInfoA, meaInfoB){ - return def.compare(meaInfoA.groupIndex, meaInfoB.groupIndex) || - def.compare(meaInfoA.index, meaInfoB.index) - ; - }); - - // Reassign measure group indexes - // Fill measure types - var M = measuresInfoList.length; - var meaTypes = new Array(M); - this._itemCrossGroupTypes.M = meaTypes; - - measuresInfoList.forEach(function(meaInfoA, index){ - meaInfoA.groupIndex = index; - meaTypes[index] = meaInfoA.type; - }); - - // Publish colgroups and colgroupIndexes, keeping only relevant information - var CG = colGroups.length, - colGroupsValues = new Array(CG), - colGroupsIndexes = new Array(CG) - ; - - colGroups.map(function(colGroup, cg){ - colGroupsValues[cg] = colGroup.values; - - var colGroupStartIndex = colGroup.startIndex; - - // The index in source *line* where each of the M measures can be read - var meaIndexes = colGroupsIndexes[cg] = new Array(M); - colGroup.measureNames.forEach(function(meaName2, localMeaIndex){ - // The measure index in VITEM - var meaIndex = measuresInfo[meaName2].groupIndex; - - // Where to read the measure in *line*? - meaIndexes[meaIndex] = R + colGroupStartIndex + localMeaIndex; - }); - }); - - this._colGroups = colGroupsValues; - this._colGroupsIndexes = colGroupsIndexes; - this.M = M; - }, - - /** - * Called once, before {@link #execute}, - * for the translation to configure the complex type. - * - * @type undefined - * @override - */ - configureType: function(){ - // Map: Dimension Group -> Item cross-groups indexes - if(this.measuresDirection === 'rows') { - throw def.error.notImplemented(); - } - - this.base(); - }, - - /** - * Default cross tab mapping from virtual item to dimensions. - * @override - */ - _configureTypeCore: function(){ - var me = this; - var itemLogicalGroup = me._itemLogicalGroup; - var itemLogicalGroupIndex = me._itemLogicalGroupIndex; - - var index = 0; - var dimsReaders = []; - - function add(dimGroupName, level, count) { - var crossEndIndex = itemLogicalGroupIndex[dimGroupName] + count; // exclusive - while(count > 0) { - var dimName = pvc.buildIndexedId(dimGroupName, level); - if(!me.complexTypeProj.isReadOrCalc(dimName)) { // Skip name if occupied and continue with next name - - // use first available slot for auto dims readers as long as within crossIndex and crossIndex + count - index = me._nextAvailableItemIndex(index); - if(index >= crossEndIndex) { - // this group has no more slots available - return; - } - - dimsReaders.push({names: dimName, indexes: index}); - - index++; // consume index - count--; - } - - level++; - } - } - - /* plot2SeriesIndexes only implemented for single-series */ - var dataPartDimName = this.options.dataPartDimName; - if(dataPartDimName && this.C === 1 && !this.complexTypeProj.isReadOrCalc(dataPartDimName)) { - // The null test is required because plot2SeriesIndexes can be a number, a string... - var plot2SeriesIndexes = this.options.plot2SeriesIndexes; - if(plot2SeriesIndexes != null){ - var seriesKeys = this._colGroups.map(function(colGroup){ - return '' + colGroup[0].v; - }); - this._plot2SeriesKeySet = this._createPlot2SeriesKeySet(plot2SeriesIndexes, seriesKeys); - } - } - - ['series', 'category', 'value'].forEach(function(dimGroupName){ - var L = itemLogicalGroup[dimGroupName]; - if(L > 0){ - add(dimGroupName, 0, L); - } - }); - - if(dimsReaders) { - dimsReaders.forEach(this.defReader, this); - } - - if(this._plot2SeriesKeySet){ - var seriesReader = this._userDimsReadersByDim.series; - if(seriesReader) { - var calcAxis2SeriesKeySet = def.fun.constant(this._plot2SeriesKeySet); - this._userRead(this._dataPartGet(calcAxis2SeriesKeySet, seriesReader), dataPartDimName); - } - } - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/translation/MatrixTranslationOper.js b/pacotes/ccc2/pvc/data/translation/MatrixTranslationOper.js deleted file mode 100755 index 7efa201..0000000 --- a/pacotes/ccc2/pvc/data/translation/MatrixTranslationOper.js +++ /dev/null @@ -1,254 +0,0 @@ - -/** - * @name pvc.data.MatrixTranslationOper - * @class Represents one translation operation, - * from a source matrix in some format to - * an enumerable of atom arrays. - * - * @extends pvc.data.TranslationOper - * @abstract - * - * @constructor - * @param {pvc.BaseChart} chart The associated chart. - * @param {pvc.data.ComplexType} complexType The complex type that will represent the translated data. - * @param {pvc.data.Data} data The data object which will be loaded with the translation result. - * @param {object} source The source matrix, in some format, to be translated. - * The source is not modified. - * @param {object} [metadata] A metadata object describing the source. - * @param {object} [options] An object with translation options. - * - * @param {boolean} [options.seriesInRows=false] - * Indicates that series are to be switched with categories. - * - * @param {Number[]} [options.plot2SeriesIndexes] - * Array of series indexes in {@link #source} that are second axis' series. - * Any non-null value is converted to an array. - * Each value of the array is also converted to a number. - * A negative value is counted from the end - * of the series values (-1 is the series last value, ...). - *

- * Note that the option 'seriesInRows' - * affects what are considered to be series values. - * - * Having determined where series are stored, - * the order of occurrence of a series value in {@link #source} - * determines its index. - *

- */ -def.type('pvc.data.MatrixTranslationOper', pvc.data.TranslationOper) -.add(/** @lends pvc.data.MatrixTranslationOper# */{ - - _initType: function(){ - this.J = this.metadata.length; - this.I = this.source.length; - - this._processMetadata(); - - this.base(); - }, - - _knownContinuousColTypes: {'numeric': 1, 'number': 1, 'integer': 1}, - - _processMetadata: function(){ - // Get the indexes of columns which are - // not stated as continuous (numeric..) - // In these, - // we can't trust their stated data type - // cause when nulls exist on the first row, - // they frequently come stated as "string"... - var knownContinColTypes = this._knownContinuousColTypes; - var columns = - def - .query(this.metadata) - // Fix indexes of colDefs - .select(function(colDef, colIndex){ - // Ensure colIndex is trustable - colDef.colIndex = colIndex; - return colDef; - }) - .where(function(colDef){ - var colType = colDef.colType; - return !colType || - knownContinColTypes[colType.toLowerCase()] !== 1; - }) - .select(function(colDef){ return colDef.colIndex; }) - .array(); - - // 1 - continuous (number, date) - // 0 - discrete (anything else) - // Assume all are continuous - var columnTypes = def.array.create(this.J, 1); - - // Number of rows in source - var I = this.I; - var source = this.source; - - // Number of columns remaining to confirm data type - var J = columns.length; - - for(var i = 0 ; i < I && J > 0 ; i++){ - var row = source[i]; - var m = 0; - while(m < J){ - var j = columns[m]; - var value = row[j]; - if(value != null){ - columnTypes[j] = this._getSourceValueType(value); - - columns.splice(m, 1); - J--; - } else { - m++; - } - } - } - - this._columnTypes = columnTypes; - }, - - // 1 - continuous (number, date) - // 0 - discrete (anything else) - /** @static */ - _getSourceValueType: function(value){ - switch(typeof value){ - case 'number': return 1; - case 'object': - if(value instanceof Date){ - return 1; - } - } - - return 0; // discrete - }, - - logSource: function(){ - var out = [ - "DATA SOURCE SUMMARY", - pvc.logSeparator, - "ROWS (" + Math.min(10, this.I) + "/" + this.I + ")" - ]; - - def - .query(this.source) - .take(10) - .each(function(row, index){ - out.push(" [" + index + "] " + pvc.stringify(row)); - }); - - if(this.I > 10){ - out.push(' ...'); - } - - out.push("COLS (" + this.J + ")"); - - var colTypes = this._columnTypes; - this - .metadata - .forEach(function(col, j){ - out.push( - " [" + j + "] " + - "'" + col.colName + "' (" + - "type: " + col.colType + ", " + - "inspected: " + (colTypes[j] ? 'continuous' : 'discrete') + - (col.colLabel ? (", label: '" + col.colLabel + "'") : "") + - ")"); - }); - - //out.push(pvc.logSeparator); - pvc.log(out.join('\n')); - }, - - /** - * Creates the set of second axis series keys - * corresponding to the specified - * plot2SeriesIndexes and seriesAtoms arrays (protected). - * - * Validates that the specified series indexes are valid - * indexes of seriesAtoms array. - * - * @param {Array} plot2SeriesIndexes Array of indexes of the second axis series values. - * @param {Array} seriesKeys Array of the data source's series atom keys. - * - * @returns {Object} A set of second axis series values or null if none. - * - * @private - * @protected - */ - _createPlot2SeriesKeySet: function(plot2SeriesIndexes, seriesKeys){ - var plot2SeriesKeySet = null, - seriesCount = seriesKeys.length; - def.query(plot2SeriesIndexes).each(function(indexText){ - // Validate - var seriesIndex = +indexText; // + -> convert to number - if(isNaN(seriesIndex)){ - throw def.error.argumentInvalid('plot2SeriesIndexes', "Element is not a number '{0}'.", [indexText]); - } - - if(seriesIndex < 0){ - if(seriesIndex <= -seriesCount){ - throw def.error.argumentInvalid('plot2SeriesIndexes', "Index is out of range '{0}'.", [seriesIndex]); - } - - seriesIndex = seriesCount + seriesIndex; - } else if(seriesIndex >= seriesCount){ - throw def.error.argumentInvalid('plot2SeriesIndexes', "Index is out of range '{0}'.", [seriesIndex]); - } - - // Set - if(!plot2SeriesKeySet){ - plot2SeriesKeySet = {}; - } - - plot2SeriesKeySet[seriesKeys[seriesIndex]] = true; - }); - - return plot2SeriesKeySet; - }, - - // TODO: docs - _dataPartGet: function(calcAxis2SeriesKeySet, seriesReader) { - - var me = this; - - var dataPartDimName = this.options.dataPartDimName; - - var dataPartDimension, - plot2SeriesKeySet, - part1Atom, - part2Atom, - outAtomsSeries = {}; - - function dataPartGet(item, outAtoms) { - /* - * First time initialization. - * Done here because *data* isn't available before. - */ - if(!dataPartDimension) { - plot2SeriesKeySet = calcAxis2SeriesKeySet(); - dataPartDimension = me.data.dimensions(dataPartDimName); - - if(pvc.debug >=3 && plot2SeriesKeySet){ - pvc.log("Second axis series values: " + - pvc.stringify(def.keys(plot2SeriesKeySet))); - } - } - - var partAtom; - seriesReader(item, outAtomsSeries); - var series = outAtomsSeries.series; - if(series != null && series.v != null){ - series = series.v; - } - - if(def.hasOwn(plot2SeriesKeySet, series)){ - partAtom = part2Atom || (part2Atom = dataPartDimension.intern("1")); - } else { - partAtom = part1Atom || (part1Atom = dataPartDimension.intern("0")); - } - - outAtoms[dataPartDimName] = partAtom; - } - - return dataPartGet; - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/translation/MetricPointChartTranslationOper.js b/pacotes/ccc2/pvc/data/translation/MetricPointChartTranslationOper.js deleted file mode 100755 index 1801eee..0000000 --- a/pacotes/ccc2/pvc/data/translation/MetricPointChartTranslationOper.js +++ /dev/null @@ -1,94 +0,0 @@ - -/** - * @name pvc.data.MetricPointChartTranslationOper - * - * @class The translation mixin of the Metric XY charts. - * - *

- * The default format is: - *

- *
- * +----------+----------+----------+----------+----------+
- * | 0        | 1        | 2        | 3        | 4        |
- * +----------+----------+----------+----------+----------+
- * | series   | x        | y        | color    | size     |
- * +----------+----------+----------+----------+----------+
- * | discrete | number   | number   | num/disc | number   |
- * +----------+----------+----------+----------+----------+
- * 
- * - *

- * Color dimensions will be continuous by default. - * If that is not the case, - * an explicit dimension valueType definition must be provided. - *

- * - * @extends pvc.data.MatrixTranslationOper - */ -def.type('pvc.data.MetricPointChartTranslationOper') -.add(/** @lends pvc.data.MetricPointChartTranslationOper# */{ - - _meaLayoutRoles: ['x', 'y', 'color', 'size'], - - configureType: function(){ - var itemTypes = this._itemTypes; - - var V = itemTypes.length; - - // VItem Indexes of continuous columns not yet being read - var freeMeaIndexes = []; - - // Idem, but for discrete columns - var freeDisIndexes = []; - - def - .range(0, V) - .each(function(j){ - if(!this._userUsedIndexes[j]){ - if(itemTypes[j] === 1){ - freeMeaIndexes.push(j); - } else { - freeDisIndexes.push(j); - } - } - }, this); - - // Distribute free measure columns by unbound measure roles - var N; - var autoDimNames = []; - var F = freeMeaIndexes.length; - if(F > 0){ - // Collect the default dimension names of the - // first F unbound roles - var R = this._meaLayoutRoles.length; - var i = 0; - while(i < R && autoDimNames.length < F){ - // If the measure role is unbound and has a default dimension, - // the next unused dimension of the default dimension group name - // is placed in autoDimNames. - // If any, this dimension will be fed with the next freeMeaIndexes - this._getUnboundRoleDefaultDimNames(this._meaLayoutRoles[i], 1, autoDimNames); - i++; - } - - N = autoDimNames.length; - if(N > 0){ - freeMeaIndexes.length = N; - this.defReader({names: autoDimNames, indexes: freeMeaIndexes}); - } - } - - // All discrete columns go to series dimensions - F = freeDisIndexes.length; - if(F > 0){ - autoDimNames.length = 0; - this._getUnboundRoleDefaultDimNames('series', F, autoDimNames); - - N = autoDimNames.length; - if(N > 0){ - freeDisIndexes.length = N; - this.defReader({names: autoDimNames, indexes: freeDisIndexes}); - } - } - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/translation/RelationalTranslationOper.js b/pacotes/ccc2/pvc/data/translation/RelationalTranslationOper.js deleted file mode 100755 index 16357df..0000000 --- a/pacotes/ccc2/pvc/data/translation/RelationalTranslationOper.js +++ /dev/null @@ -1,352 +0,0 @@ - -/** - * @name pvc.data.RelationalTranslationOper - * - * @class Represents one translation operation, - * from a source matrix in relational format to - * an enumerable of atom arrays. - * - *

- * The default matrix-relational format is: - *

- *
- * ---------------------------
- *    0   |    1     |   2
- * ---------------------------
- * series | category | value
- * ---------------------------
- *    T   |     A    |   12
- *    T   |     B    |   45
- *    Q   |     A    |   11
- *    Q   |     B    |   99
- *    Z   |     B    |    3
- * 
- *

- * If the option seriesInRows is true - * the indexes of series and categories are switched. - *

- *

- * If the option measuresIndexes is specified, - * additional value dimensions are created to receive the specified columns. - * Note that these indexes may consume series and/or category indexes as well. - *

- *

- * If only two metadata columns are provided, - * then a dummy 'series' column, with the constant null value, is added automatically. - *

- * - * @extends pvc.data.MatrixTranslationOper - * - * @constructor - * @param {pvc.BaseChart} chart The associated chart. - * @param {pvc.data.ComplexType} complexType The complex type that will represent the translated data. - * @param {object} source The matrix-relational array to be translated. - * The source is not modified. - * @param {object} [metadata] A metadata object describing the source. - * - * @param {object} [options] An object with translation options. - * See additional available options in {@link pvc.data.MatrixTranslationOper}. - * - * @param {(number|string)[]|number|string} [options.measuresIndexes] - * An array of indexes of columns of the source matrix - * that contain value dimensions. - *

- * Multiple 'value' dimensions ('value', 'value2', 'value3', ...) - * are bound in order to the specified indexes. - *

- *

- * The option 'plot2SeriesIndexes' - * is incompatible with and - * takes precedence over - * this one. - *

- *

- * The indexes can be numbers or strings that represent numbers. - * It is also possible to specify a single index instead of an array. - *

- */ -def.type('pvc.data.RelationalTranslationOper', pvc.data.MatrixTranslationOper) -.add(/** @lends pvc.data.RelationalTranslationOper# */{ - M: 0, // number of measures - C: 0, // number of categories - S: 0, // number of series - - _processMetadata: function(){ - - this.base(); - - var metadata = this.metadata; - - var J = this.J; // metadata.length - - // Split between series and categories - var C = this.options.categoriesCount; - if(C != null && (!isFinite(C) || C < 0)){ - C = 0; - } - - var S; - - // Assuming duplicate valuesColIndexes is not valid - // (v1 did not make this assumption) - var valuesColIndexes, M; - if(this.options.isMultiValued){ - valuesColIndexes = pvc.parseDistinctIndexArray(this.options.measuresIndexes, J - 1); - M = valuesColIndexes ? valuesColIndexes.length : 0; - } - - var D; // discrete count = D = S + C - if(M == null){ - if(J > 0 && J <= 3 && (C == null || C === 1) && S == null){ - // V1 Stability requirement - // Measure columns with all values = null, - // would be detected as type string, - // and not be chosen as measures. - M = 1; - valuesColIndexes = [J - 1]; - C = J >= 2 ? 1 : 0; - S = J >= 3 ? 1 : 0; - D = C + S; - - } else if(C != null && C >= J){ - D = J; - C = J; - S = 0; - M = 0; - } else { - // finite C wins over M, and by last S - var Mmax = C != null ? (J - C) : Infinity; // >= 1 - - // colIndex has already been fixed on _processMetadata - valuesColIndexes = def - .query(metadata) - .where(function(colDef, index){ - return this._columnTypes[index] !== 0; // 0 = discrete - }, this) - .select(function(colDef){ return colDef.colIndex; }) - .take(Mmax) - .array() - ; - - M = valuesColIndexes.length; - } - } - - if(D == null){ - // M wins over C - D = J - M; - if(D === 0){ - S = C = 0; - } else if(C != null){ - if(C > D){ - C = D; - S = 0; - } else { - S = D - C; - } - } else { - // Distribute between categories and series - S = D > 1 ? 1 : 0; - C = D - S; - } - } - - var seriesInRows = this.options.seriesInRows; - var colGroupSpecs = []; - if(D){ - if(S && !seriesInRows){ - colGroupSpecs.push({name: 'S', count: S}); - } - - if(C){ - colGroupSpecs.push({name: 'C', count: C}); - } - - if(S && seriesInRows){ - colGroupSpecs.push({name: 'S', count: S}); - } - } - - if(M){ - colGroupSpecs.push({name: 'M', count: M}); - } - - var availableInputIndexes = def.range(0, J).array(); - - // If valuesColIndexes != null, these are reserved for values - if(valuesColIndexes){ - // Remove these indexes from available indexes - valuesColIndexes.forEach(function(inputIndex){ - availableInputIndexes.splice(inputIndex, 1); - }); - } - - // Set the fields with actual number of columns of each group - // Assign the input indexes of each group (Layout) - var specsByName = {}; - colGroupSpecs.forEach(function(groupSpec){ - var count = groupSpec.count; - var name = groupSpec.name; - - // Index group by name - specsByName[name] = groupSpec; - - if(valuesColIndexes && name === 'M'){ - groupSpec.indexes = valuesColIndexes; - } else { - groupSpec.indexes = availableInputIndexes.splice(0, count); - } - }, this); - - this.M = M; - this.S = S; - this.C = C; - - // Compose the total permutation array - // that transforms the input into the virtual item "normal form": - // S* C* M* - var itemPerm = []; - ['S', 'C', 'M'].forEach(function(name){ - var groupSpec = specsByName[name]; - if(groupSpec){ - def.array.append(itemPerm, groupSpec.indexes); - } - }); - - var colTypes = this._columnTypes; - this._itemTypes = itemPerm.map(function(index){ return colTypes[index]; }); - - // The start indexes of each column group - this._itemCrossGroupIndex = { - S: 0, - C: this.S, - M: this.S + this.C - }; - - this._itemPerm = itemPerm; - - if(pvc.debug >= 3){ - var out = [ - "RELATIONAL TRANSLATOR MAPPING", - pvc.logSeparator, - "[" + - colGroupSpecs.map(function(groupSpec){ - return def.array.create(groupSpec.count, groupSpec.name).join(''); - }) - .join(' ') + - "]" - ]; - - pvc.log(out.join("\n")); - } - }, - - /** - * Default cross tab mapping from virtual item to dimensions. - * @override - */ - _configureTypeCore: function(){ - var me = this; - var index = 0; - var dimsReaders = []; - - function add(dimGroupName, colGroupName, level, count) { - var groupEndIndex = me._itemCrossGroupIndex[colGroupName] + count; // exclusive - while(count > 0) { - var dimName = pvc.buildIndexedId(dimGroupName, level); - if(!me.complexTypeProj.isReadOrCalc(dimName)) { // Skip name if occupied and continue with next name - - // use first available slot for auto dims readers as long as within the group slots - index = me._nextAvailableItemIndex(index); - if(index >= groupEndIndex) { - // this group has no more slots available - return; - } - - dimsReaders.push({names: dimName, indexes: index}); - - index++; // consume index - count--; - } - - level++; - } - } - - if(this.S > 0){ - add('series', 'S', 0, this.S); - } - - if(this.C > 0){ - add('category', 'C', 0, this.C); - } - - if(this.M > 0) { - add('value', 'M', 0, this.M); - } - - if(dimsReaders) { - dimsReaders.forEach(this.defReader, this); - } - - // ---- - // The null test is required because plot2SeriesIndexes can be a number, a string... - var plot2SeriesIndexes = this.options.plot2SeriesIndexes; - if(plot2SeriesIndexes != null){ - var seriesReader = this._userDimsReadersByDim.series; - if(seriesReader) { - var dataPartDimName = this.options.dataPartDimName; - this._userRead(relTransl_dataPartGet.call(this, plot2SeriesIndexes, seriesReader), dataPartDimName); - } - } - }, - - // Permutes the input rows - _executeCore: function(){ - var dimsReaders = this._getDimensionsReaders(); - var permIndexes = this._itemPerm; - - return def.query(this._getItems()) - .select(function(item){ - - item = pv.permute(item, permIndexes); - - return this._readItem(item, dimsReaders); - }, this); - } -}); - -/** - * Obtains the dimension reader for dimension 'dataPart'. - * - * @name pvc.data.RelationalTranslationOper#_dataPartGet - * @function - * @param {Array} plot2SeriesIndexes The indexes of series that are to be shown on the second axis. - * @param {function} seriesReader Dimension series atom getter. - * @type function - */ -function relTransl_dataPartGet(plot2SeriesIndexes, seriesReader) { - var me = this; - - /* Defer calculation of plot2SeriesKeySet because *data* isn't yet available. */ - function calcAxis2SeriesKeySet() { - var atoms = {}; - var seriesKeys = def.query(me.source) - .select(function(item){ - seriesReader(item, atoms); - var value = atoms.series; - if(value != null && value.v != null){ - value = value.v; - } - - return value || null; - }) - /* distinct excludes null keys */ - .distinct() - .array(); - - return me._createPlot2SeriesKeySet(plot2SeriesIndexes, seriesKeys); - } - - return this._dataPartGet(calcAxis2SeriesKeySet, seriesReader); -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/data/translation/TranslationOper.js b/pacotes/ccc2/pvc/data/translation/TranslationOper.js deleted file mode 100755 index a033471..0000000 --- a/pacotes/ccc2/pvc/data/translation/TranslationOper.js +++ /dev/null @@ -1,477 +0,0 @@ - -/** - * Initializes a translation operation. - * - * @name pvc.data.TranslationOper - * @class Represents one translation operation - * from some data source format to the list of atoms format. - * - * @property {pvc.BaseChart} chart The associated chart. - * @property {pvc.data.ComplexType} complexType The complex type that represents the translated data. - * @property {pvc.data.Data} data The data object which will be loaded with the translation result. - * @property {object} source The source object, of some format, being translated. - * @property {object} metadata A metadata object describing the source. - * @property {object} options An object with translation options. - * - * @constructor - * @param {pvc.BaseChart} chart The associated chart. - * @param {pvc.data.ComplexTypeProject} complexTypeProj The complex type project that will represent the translated data. - * @param {object} source The source object, of some format, to be translated. - * The source is not modified. - * @param {object} [metadata] A metadata object describing the source. - * @param {object} [options] An object with translation options. - * Options are translator specific. - * TODO: missing common options here - */ -def.type('pvc.data.TranslationOper') -.init(function(chart, complexTypeProj, source, metadata, options){ - this.chart = chart; - this.complexTypeProj = complexTypeProj; - this.source = source; - this.metadata = metadata || {}; - this.options = options || {}; - - this._initType(); - - if(pvc.debug >= 4) { - this._logItems = true; - this._logItemCount = 0; - } -}) -.add(/** @lends pvc.data.TranslationOper# */{ - - _logItems: false, - - /** - * Logs the contents of the source and metadata properties. - */ - logSource: def.method({isAbstract: true}), - - /** - * Obtains the number of fields of the virtual item. - *

- * The default implementation returns the length of the metadata. - *

- * - * @type number - * @virtual - */ - virtualItemSize: function(){ - return this.metadata.length; - }, - - freeVirtualItemSize: function(){ - return this.virtualItemSize() - this._userUsedIndexesCount; - }, - - /** - * Defines a dimension reader. - * - * @param {object} dimReaderSpec A dimensions reader specification. - * - * @type undefined - */ - defReader: function(dimReaderSpec){ - /*jshint expr:true */ - dimReaderSpec || def.fail.argumentRequired('readerSpec'); - - var dimNames; - if(typeof dimReaderSpec === 'string'){ - dimNames = dimReaderSpec; - } else { - dimNames = dimReaderSpec.names; - } - - if(typeof dimNames === 'string'){ - dimNames = dimNames.split(/\s*\,\s*/); - } else { - dimNames = def.array.as(dimNames); - } - - // Consumed/Reserved virtual item indexes - var indexes = def.array.as(dimReaderSpec.indexes); - if(indexes) { - indexes.forEach(this._userUseIndex, this); - } - - var hasDims = !!(dimNames && dimNames.length); - var reader = dimReaderSpec.reader; - if(!reader) { - if(hasDims){ - return this._userCreateReaders(dimNames, indexes); // -> indexes, possibly expanded - } // else a reader that only serves to exclude indexes - } else { - hasDims || def.fail.argumentRequired('reader.names', "Required argument when a reader function is specified."); - - this._userRead(reader, dimNames); - } - - return indexes; - }, - - /** - * Called once, before {@link #execute}, - * for the translation to configure the complex type (abstract). - * - *

- * If this method is called more than once, - * the consequences are undefined. - *

- * - * @name pvc.data.TranslationOper#configureType - * @function - * @type undefined - * @virtual - */ - configureType: function(){ - this._configureTypeCore(); - }, - - /** @abstract */ - _configureTypeCore: def.method({isAbstract: true}), - - _initType: function(){ - this._userDimsReaders = []; - this._userDimsReadersByDim = {}; - - this._userItem = []; - - this._userUsedIndexes = {}; - this._userUsedIndexesCount = 0; - - // ------------- - - var userDimReaders = this.options.readers; - if(userDimReaders) { - userDimReaders.forEach(this.defReader, this); - } - - var multiChartIndexes = pvc.parseDistinctIndexArray(this.options.multiChartIndexes); - if(multiChartIndexes) { - this._multiChartIndexes = this.defReader({names: 'multiChart', indexes: multiChartIndexes }); - } - }, - - _userUseIndex: function(index){ - index = +index; // to number - - /*jshint expr:true */ - (index >= 0) || def.fail.argumentInvalid('index', "Invalid reader index: '{0}'.", [index]); - - !def.hasOwn(this._userUsedIndexes, index) || - def.fail.argumentInvalid('index', "Virtual item index '{0}' is already assigned.", [index]); - - this._userUsedIndexes[index] = true; - this._userUsedIndexesCount++; - this._userItem[index] = true; - - return index; - }, - - _userCreateReaders: function(dimNames, indexes){ - if(!indexes){ - indexes = []; - } else { - // Convert indexes to number - indexes.forEach(function(index, j){ - indexes[j] = +index; - }); - } - - // Distribute indexes to names, from left to right - // Excess indexes go to the last *group* name - // Missing indexes are padded from available indexes starting from the last provided index - // If not enough available indexes exist, those names end up reading undefined - var I = indexes.length, - N = dimNames.length, - dimName; - - if(N > I) { - // Pad indexes - var nextIndex = I > 0 ? (indexes[I - 1] + 1) : 0; - do{ - nextIndex = this._nextAvailableItemIndex(nextIndex); - indexes[I] = nextIndex; - this._userUseIndex(nextIndex); - - I++; - }while(N > I); - } - - // If they match, it's one-one name <-- index - var L = (I === N) ? N : (N - 1); - - // The first N-1 names get the first N-1 indexes - for(var n = 0 ; n < L ; n++) { - dimName = dimNames[n]; - this._userRead(this._propGet(dimName, indexes[n]), dimName); - } - - // The last name is the dimension group name that gets all remaining indexes - if(L < N) { - // TODO: make a single reader that reads all atoms?? - // Last is a *group* START name - var splitGroupName = pvc.splitIndexedId(dimNames[N - 1]), - groupName = splitGroupName[0], - level = def.nullyTo(splitGroupName[1], 0); - - for(var i = L ; i < I ; i++, level++) { - dimName = pvc.buildIndexedId(groupName, level); - this._userRead(this._propGet(dimName, indexes[i]), dimName); - } - } - - return indexes; - }, - - _userRead: function(reader, dimNames){ - /*jshint expr:true */ - def.fun.is(reader) || def.fail.argumentInvalid('reader', "Reader must be a function."); - - if(def.array.is(dimNames)){ - dimNames.forEach(function(name){ - this._readDim(name, reader); - }, this); - } else { - this._readDim(dimNames, reader); - } - - this._userDimsReaders.push(reader); - }, - - _readDim: function(name, reader){ - this.complexTypeProj.readDim(name); - this._userDimsReadersByDim[name] = reader; - }, - - /** - * Performs the translation operation for a data instance. - * - *

- * The returned atoms are interned in - * the dimensions of the specified data instance. - *

- * - *

- * If this method is called more than once, - * the consequences are undefined. - *

- * - * @param {pvc.data.Data} data The data object in whose dimensions returned atoms are interned. - * - * @returns {def.Query} An enumerable of {@link pvc.data.Atom[]} - */ - execute: function(data){ - this.data = data; - - return this._executeCore(); - }, - - /** - * Obtains an enumerable of translated atoms (virtual). - * - *

- * The default implementation applies - * every dimensions reader returned by {@link #_getDimensionsReaders} - * to every item returned by {@link #_getItems}. - * - * Depending on the underlying data source format - * this may or may not be a good translation strategy. - * Override to apply a different one. - *

- * - * @returns {def.Query} An enumerable of {@link pvc.data.Atom[]} - * @virtual - */ - _executeCore: function(){ - var dimsReaders = this._getDimensionsReaders(); - - return def.query(this._getItems()) - .select(function(item){ - return this._readItem(item, dimsReaders); - }, this); - }, - - /** - * Obtains an enumerable of items to translate (virtual). - * - *

- * The default implementation assumes that {@link #source} - * is directly the desired enumerable of items. - *

- * - * @type def.Query - */ - _getItems: function(){ - return this.source; - }, - - /** - * Obtains the dimensions readers array (virtual). - * - *

- * Each dimensions reader function reads one or more dimensions - * from a source item. - * It has the following signature: - *

- *
-     * function(item : any) : pvc.data.Atom[] | pvc.data.Atom
-     * 
- * - *

- * The default implementation simply returns the {@link #_userDimsReaders} field. - *

- * - * @name _getDimensionsReaders - * @type function[] - * @virtual - */ - _getDimensionsReaders: function(){ - return this._userDimsReaders; - }, - - /** - * Applies all the specified dimensions reader functions to an item - * and sets the resulting atoms in a specified array (virtual). - * - * @param {any} item The item to read. - * @param {function[]} dimsReaders An array of dimensions reader functions. - * @returns {map(string any)} A map of read raw values by dimension name. - * @virtual - */ - _readItem: function(item, dimsReaders) { - // This function is performance critical and so does not use forEach - // or array helpers, avoiding function calls, closures, etc. - var logItem = this._logItems; - if(logItem) { - var logItemCount = this._logItemCount; - if(logItemCount < 10){ - pvc.log('virtual item [' + this._logItemCount + ']: ' + pvc.stringify(item)); - this._logItemCount++; - } else { - pvc.log('...'); - logItem = this._logItems = false; - } - } - - var r = 0, - R = dimsReaders.length, - a = 0, - data = this.data, - valuesByDimName = {}; - - while(r < R) { - dimsReaders[r++].call(data, item, valuesByDimName); - } - - if(logItem) { - var atoms = {}; - for(var dimName in valuesByDimName){ - var atom = valuesByDimName[dimName]; - if(def.object.is(atom)){ - atom = ('v' in atom) ? atom.v : ('value' in atom) ? atom.value : '...'; - } - - atoms[dimName] = atom; - } - - pvc.log('-> read: ' + pvc.stringify(atoms)); - } - - return valuesByDimName; - }, - - /** - * Given a dimension name and a property name, - * creates a corresponding dimensions reader (protected). - * - * @param {string} dimName The name of the dimension on which to intern read values. - * @param {string} prop The property name to read from each item. - * @param {object} [keyArgs] Keyword arguments. - * @param {boolean} [keyArgs.ensureDim=true] Creates a dimension with the specified name, with default options, if one does not yet exist. - * - * @type function - */ - _propGet: function(dimName, prop) { - - function propGet(item, atoms){ - atoms[dimName] = item[prop]; - } - - return propGet; - }, - - /** - * Given a dimension name and a raw value of that dimension, - * creates a dimensions reader that returns the corresponding atom, - * regardless of the source item supplied to it (protected). - * - * @param {string} dimName The name of the dimension on which to intern constRawValue. - * @param {string} constRawValue The raw value. - * - * @param {object} [keyArgs] Keyword arguments. - * @param {boolean} [keyArgs.ensureDim=true] Creates a dimension with the specified name, with default options, if one does not yet exist. - * - * @type function - */ - _constGet: function(dimName, constRawValue, keyArgs) { - var me = this, - constAtom; - - function constGet(item, atoms) { - atoms[dimName] = - constAtom || - (constAtom = me.data.dimensions(dimName).intern(constRawValue)); - } - - return constGet; - }, - - // TODO: docs - _nextAvailableItemIndex: function(index, L){ - if(index == null) { - index = 0; - } - if(L == null){ - L = Infinity; - } - - while(index < L && def.hasOwn(this._userItem, index)) { - index++; - } - - return index < L ? index : -1; - }, - - _getUnboundRoleDefaultDimNames: function(roleName, count, dims, level){ - var role = this.chart.visualRoles(roleName, {assertExists: false}); - if(role && !role.isPreBound()){ - var dimGroupName = role.defaultDimensionName; - if(dimGroupName){ - dimGroupName = dimGroupName.match(/^(.*?)(\*)?$/)[1]; - - if(!dims){ - dims = []; - } - - if(level == null){ - level = 0; - } - - if(count == null) { - count = 1; - } - - // Already bound dimensions count - while(count--){ - var dimName = pvc.buildIndexedId(dimGroupName, level++); - if(!this.complexTypeProj.isReadOrCalc(dimName)){ - dims.push(dimName); - } - } - - return dims.length ? dims : null; - } - } - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvc.color.js b/pacotes/ccc2/pvc/pvc.color.js deleted file mode 100755 index 0ccb4f7..0000000 --- a/pacotes/ccc2/pvc/pvc.color.js +++ /dev/null @@ -1,518 +0,0 @@ - -// Colors utility -def.scope(function(){ - - pvc.color = { - scale: colorScale, - scales: colorScales - }; - - // -------------------------- - // exported - - /** - * Creates color scales of a specified type for datums grouped by a category. - * - * @name pvc.color.scales - * @function - * @param {object} keyArgs Keyword arguments. - * See {@link pvc.color.scale} for available arguments. - * - * @param {def.Query} keyArgs.data - * A {@link pvc.data.Data} that is the result of grouping datums along what are here called "category" dimensions. - *

- * One (possibly equal) color scale is returned per leaf data, indexed by the leaf's absolute key (see {@link pvc.data.Data#absKey}). - *

- * @param {boolean} [keyArgs.normPerBaseCategory=false] Indicates that a different color scale should be computed per distinct data category. - * - * @type function - */ - function colorScales(keyArgs){ - /*jshint expr:true */ - keyArgs || def.fail.argumentRequired('keyArgs'); - - var type = keyArgs.type || def.fail.argumentRequired('keyArgs.type'); - - switch (type) { - case 'linear': return new pvc.color.LinearScalesBuild(keyArgs).buildMap(); - case 'discrete': return new pvc.color.DiscreteScalesBuild(keyArgs).buildMap(); - case 'normal': return new pvc.color.NormalScalesBuild(keyArgs).buildMap(); // TODO - } - - throw def.error.argumentInvalid('scaleType', "Unexistent scale type '{0}'.", [type]); - } - - /** - * Creates a color scale of a specified type. - * - * @name pvc.color.scale - * @function - * @param {object} keyArgs Keyword arguments. - * See {@link pvc.color.scales} for available arguments. - * - * @param {def.Query} keyArgs.data A {@link pvc.data.Data} instance that - * may be used to obtain the domain of the color scale. - * - * @param {string} keyArgs.type The type of color scale. - *

- * Valid values are 'linear', 'discrete' and 'normal' (normal probability distribution). - *

- * @param {string|pv.color} [keyArgs.colorMin] The minimum color. - * @param {string|pv.color} [keyArgs.colorMax] The maximum color. - * @param {string|pv.color} [keyArgs.colorNull] The color shown for null values. - * @param {(string|pv.color)[]} [keyArgs.colors] Array of colors. - *

- * This argument is ignored if both minimum and maximum colors are specified. - * Otherwise, if only one of minimum or maximum is specified, it is prepended or appended to - * the color range array, respectively. - *

- *

- * When unspecified, the color range is assumed to be 'red', 'yellow' and 'green'. - *

- * @param {string} keyArgs.colorDimension The name of the data dimension that is the domain of the color scale. - * @param {object[]} [keyArgs.colorDomain] An array of domain values to match colors in the color range. - * - * @type function - */ - function colorScale(keyArgs){ - /*jshint expr:true */ - keyArgs || def.fail.argumentRequired('keyArgs'); - - var type = keyArgs.type || def.fail.argumentRequired('keyArgs.type'); - - switch (type) { - case 'linear': return new pvc.color.LinearScalesBuild(keyArgs).build(); - case 'discrete': return new pvc.color.DiscreteScalesBuild(keyArgs).build(); - case 'normal': return new pvc.color.NormalScalesBuild(keyArgs).build(); - } - - throw def.error.argumentInvalid('scaleType', "Unexistent scale type '{0}'.", [type]); - } - - // -------------------------- - // private - - /** - * @class Represents one creation/build of a set of scale functions. - * @abstract - */ - def - .type('pvc.color.ScalesBuild') - .init(function(keyArgs){ - this.keyArgs = keyArgs; - this.data = keyArgs.data || def.fail.argumentRequired('keyArgs.data'); - this.domainDimName = keyArgs.colorDimension || def.fail.argumentRequired('keyArgs.colorDimension'); - this.domainDim = this.data.dimensions(this.domainDimName); - - var dimType = this.domainDim.type; - if(!dimType.isComparable) { - this.domainComparer = null; - pvc.log("Color value dimension should be comparable. Generated color scale may be invalid."); - } else { - this.domainComparer = function(a, b){ return dimType.compare(a, b); }; - } - - this.nullRangeValue = keyArgs.colorNull ? pv.color(keyArgs.colorNull) : pv.Color.transparent; - - this.domainRangeCountDif = 0; - }) - .add(/** @lends pvc.color.ScalesBuild# */{ - /** - * Builds one scale function. - * - * @type pv.Scale - */ - build: function(){ - this.range = this._getRange(); - this.desiredDomainCount = this.range.length + this.domainRangeCountDif; - - var domain = this._getDomain(); - return this._createScale(domain); - }, - - /** - * Builds a map from category keys to scale functions. - * - * @type object - */ - buildMap: function(){ - this.range = this._getRange(); - this.desiredDomainCount = this.range.length + this.domainRangeCountDif; - - var createCategoryScale; - - /* Compute a scale-function per data category? */ - if(this.keyArgs.normPerBaseCategory){ - /* Ignore args' domain and calculate from data of each category */ - createCategoryScale = function(leafData){ - // Create a domain from leafData - var domain = this._ensureDomain(null, false, leafData); - return this._createScale(domain); - }; - } else { - var domain = this._getDomain(), - scale = this._createScale(domain); - - createCategoryScale = def.fun.constant(scale); - } - - return this._createCategoryScalesMap(createCategoryScale); - }, - - _createScale: def.method({isAbstract: true}), - - _createCategoryScalesMap: function(createCategoryScale){ - return this.data.children() - .object({ - name: function(leafData){ return leafData.absKey; }, - value: createCategoryScale, - context: this - }); - }, - - _getRange: function(){ - var keyArgs = this.keyArgs, - range = keyArgs.colors || ['red', 'yellow','green']; - - if(keyArgs.colorMin != null && keyArgs.colorMax != null){ - - range = [keyArgs.colorMin, keyArgs.colorMax]; - - } else if (keyArgs.colorMin != null){ - - range.unshift(keyArgs.colorMin); - - } else if (keyArgs.colorMax != null){ - - range.push(keyArgs.colorMax); - } - - return range.map(function(c) { return pv.color(c); }); - }, - - _getDataExtent: function(data){ - - var extent = data.dimensions(this.domainDimName).extent({visible: true}); - if(!extent) { // No atoms... - return null; - } - - var min = extent.min.value, - max = extent.max.value; - - if(max == min){ - if(max >= 1){ - min = max - 1; - } else { - max = min + 1; - } - } - - return {min: min, max: max}; - }, - - _getDomain: function() { - var domain = this.keyArgs.colorDomain; - if(domain != null){ - if(this.domainComparer) { - domain.sort(this.domainComparer); - } - - if(domain.length > this.desiredDomainCount){ - // More domain points than needed for supplied range - domain = domain.slice(0, this.desiredDomainCount); - } - } else { - // This ends up being padded...in ensureDomain - domain = []; - } - - return this._ensureDomain(domain, true, this.data); - }, - - _ensureDomain: function(domain, doDomainPadding, data) { - var extent; - - if(domain && doDomainPadding){ - /* - * If domain does not have as many values as there are colors (taking domainRangeCountDif into account), - * it is *completed* with the extent calculated from data. - * (NOTE: getArgsDomain already truncates the domain to number of colors) - */ - var domainPointsMissing = this.desiredDomainCount - domain.length; - if(domainPointsMissing > 0){ - extent = this._getDataExtent(data); - if(extent){ - // Assume domain is sorted - switch(domainPointsMissing){ // + 1 in discrete ????? - case 1: - if(this.domainComparer) { - def.array.insert(domain, extent.max, this.domainComparer); - } else { - domain.push(extent.max); - } - break; - - case 2: - if(this.domainComparer) { - def.array.insert(domain, extent.min, this.domainComparer); - def.array.insert(domain, extent.max, this.domainComparer); - } else { - domain.unshift(extent.min); - domain.push(extent.max); - } - break; - - default: - /* Ignore args domain altogether */ - if(pvc.debug >= 2){ - pvc.log("Ignoring option 'colorDomain' due to unsupported length." + - def.format(" Should have '{0}', but instead has '{1}'.", [this.desiredDomainCount, domain.length])); - } - domain = null; - } - } - } - } - - if(!domain) { - /*jshint expr:true */ - extent || (extent = this._getDataExtent(data)); - if(extent){ - var min = extent.min, - max = extent.max; - var step = (max - min) / (this.desiredDomainCount - 1); - domain = pv.range(min, max + step, step); - } - } - - return domain; - } - }); - - - def - .type('pvc.color.LinearScalesBuild', pvc.color.ScalesBuild) - .add(/** @lends pvc.color.LinearScalesBuild# */{ - - _createScale: function(domain){ - var scale = pv.Scale.linear(); - - if(domain){ - scale.domain.apply(scale, domain); - } - - scale.range.apply(scale, this.range); - - return scale; - } - }); - - def - .type('pvc.color.DiscreteScalesBuild', pvc.color.ScalesBuild) - .init(function(keyArgs){ - this.base(keyArgs); - - this.domainRangeCountDif = 1; - }) - .add(/** @lends pvc.color.DiscreteScalesBuild# */{ - - /* - * Dmin DMax C - * -------------------- - * - <=d0 c0 - * >d0 <=d1 c1 - * >d1 <=d2 c2 - * .. - * >dN-3 <=dN-2 cN-2 - * - * >dN-2 - cN-1 - */ - //d0--cR0--d1--cR1--d2 - _createScale: function(domain){ - var Dl = domain.length - 1, - range = this.range, - nullRangeValue = this.nullRangeValue, - Rl = range.length - 1; - - function scale(val){ - if(val == null) { - return nullRangeValue; - } - - for(var i = 0 ; i < Dl ; i++){ // i <= D - 2 => domain[D-1] - if(val <= domain[i + 1]){ - return range[i]; - } - } - - // > domain[Dl] - return range[Rl]; - } - - // TODO: Not a real scale; - // some methods won't work on the result of by, by1 and transform. - // Give it a bit of protovis looks - def.copy(scale, pv.Scale.common); - - return scale; - } - }); - - /* TODO */ - - /*********** - * compute an array of fill-functions. Each column out of "colAbsValues" - * gets it's own scale function assigned to compute the color - * for a value. Currently supported scales are: - * - linear (from min to max - * - normal distributed from -numSD*sd to numSD*sd - * (where sd is the standard deviation) - ********/ - /* - getNormalColorScale: function (data, colAbsValues, origData){ - var fillColorScaleByColKey; - var options = this.chart.options; - if (options.normPerBaseCategory) { - // compute the mean and standard-deviation for each column - var myself = this; - - var mean = pv.dict(colAbsValues, function(f){ - return pv.mean(data, function(d){ - return myself.getValue(d[f]); - }) - }); - - var sd = pv.dict(colAbsValues, function(f){ - return pv.deviation(data, function(d){ - myself.getValue(d[f]); - }) - }); - - // compute a scale-function for each column (each key) - fillColorScaleByColKey = pv.dict(colAbsValues, function(f){ - return pv.Scale.linear() - .domain(-options.numSD * sd[f] + mean[f], - options.numSD * sd[f] + mean[f]) - .range(options.colorMin, options.colorMax); - }); - - } else { // normalize over the whole array - - var mean = 0.0, sd = 0.0, count = 0; - for (var i=0; i - * d0 d1 d2 d3 dD-2 dD-1 (linear) - * - * - * Mode 1 - Domain divider points - * - * User specifies: - * # D domain divider points - * # R = D+1 range points - * - * //////////////////////////// - * D=0, R=1 - * - * r0 - * ... - * - * - * //////////////////////////// - * D=1, R=2 - * - * r0 ] r1 - * ... --+-- ... - * d0 - * - * - * //////////////////////////// - * D=2, R=3 - * - * r0 ] r1 ] r2 - * ... --+------+-- ... - * d0 d1 - * - * - * //////////////////////////// - * D=3, R=4 - * - * r0 ] r1 ] r2 ] r3 - * ... --+------+------+-- ... - * d0 d1 d2 - * - * ... - * - * Mode 2 - Domain dividers determination from data extent - * - * //////////////////////////// (inf. = sup.) - * Special case - * Only one color is used (the first one, for example) - * - * r0 - * - * //////////////////////////// (inf. < sup.) - * C=1 => constant color - * - * r0 - * +--------+ - * I S - * - * //////////////////////////// - * C=2 => N=1 (1 divider point) - * - * B = (S-I)/2 - * - * C0 ] C1 - * +--------+--------+ - * I d0 S - * B B - * - * //////////////////////////// - * C=3 => N=2 (2 divider points) - * - * B = (S-I)/3 - * - * C0 ] C1 ] C2 - * +--------+--------+--------+ - * I d0 d1 S - * B B B - * - * ... - * - */ -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvc.js b/pacotes/ccc2/pvc/pvc.js deleted file mode 100755 index edcf1e7..0000000 --- a/pacotes/ccc2/pvc/pvc.js +++ /dev/null @@ -1,1568 +0,0 @@ - -/*global pvc:true */ -var pvc = def.globalSpace('pvc', { - // 0 - off - // 1 - errors - // 2 - errors, warnings - // 3 - errors, warnings, info - // 4 - verbose - // 5 - trash - // ... - debug: 0 -}); - -// Begin private scope -(function(){ - - // Check URL debug and debugLevel - (function(){ - /*global window:true*/ - if((typeof window.location) !== 'undefined'){ - var url = window.location.href; - if(url && (/\bdebug=true\b/).test(url)){ - var m = /\bdebugLevel=(\d+)/.exec(url); - pvc.debug = m ? (+m[1]) : 3; - } - } - }()); - - // goldenRatio proportion - // ~61.8% ~ 38.2% - //pvc.goldenRatio = (1 + Math.sqrt(5)) / 2; - - pvc.invisibleFill = 'rgba(127,127,127,0.00001)'; - - pvc.logSeparator = "------------------------------------------"; - - var arraySlice = pvc.arraySlice = Array.prototype.slice; - - pvc.setDebug = function(level){ - level = +level; - pvc.debug = isNaN(level) ? 0 : level; - - installPvcLog(); - - syncTipsyLog(); - - return pvc.debug; - }; - - /*global console:true*/ - - pvc._installLog = function(o, pto, pfrom, prompt){ - if(!pfrom) { - pfrom = pto; - } - var c = console; - var m = c[pfrom] || c.log; - var fun; - if(m){ - var mask = prompt + ": %s"; - if(!def.fun.is(m)){ - // For IE these are not functions...but simply objects - // Bind is not available or may be a polyfill that won't work... - - var apply = Function.prototype.apply; - fun = function(){ - apply.call(m, c, def.array.append([mask], arguments)); - }; - } else { - // Calls to fun are like direct calls to m... - // and capture file and line numbers correctly! - fun = m.bind(console, mask); - } - } - - o[pto] = fun; - }; - - function installPvcLog(){ - if (pvc.debug && typeof console !== "undefined"){ - ['log', 'info', ['trace', 'debug'], 'error', 'warn', 'group', 'groupEnd'] - .forEach(function(ps){ - ps = ps instanceof Array ? ps : [ps, ps]; - - pvc._installLog(pvc, ps[0], ps[1], '[pvChart]'); - }); - } else { - if(pvc.debug > 1){ - pvc.debug = 1; - } - - ['log', 'info', 'trace', 'warn', 'group', 'groupEnd'] - .forEach(function(p){ - pvc[p] = def.noop; - }); - - pvc.error = function(e){ - if(e && typeof e === 'object' && e.message){ - e = e.message; - } - - throw new Error("[pvChart ERROR]: " + e); - }; - } - } - - installPvcLog(); - - pvc.logError = pvc.error; - - // Redirect protovis error handler - pv.error = pvc.error; - - function syncTipsyLog(){ - var tip = pv.Behavior.tipsy; - if(tip && tip.setDebug){ - tip.setDebug(pvc.debug); - tip.log = pvc.log; - } - } - - syncTipsyLog(); - - /** - * Gets or sets the default CCC compatibility mode. - *

- * Use Infinity for the latest version. - * Use 1 for CCC version 1. - *

- * - * @param {number} [compatVersion] The new compatibility version. - */ - pvc.defaultCompatVersion = function(compatVersion){ - var defaults = pvc.BaseChart.prototype.defaults; - if(compatVersion != null){ - return defaults.compatVersion = compatVersion; - } - - return defaults.compatVersion; - }; - - pvc.cloneMatrix = function(m){ - return m.map(function(d){ - return d.slice(); - }); - }; - - pvc.stringify = function(t, keyArgs){ - var maxLevel = def.get(keyArgs, 'maxLevel') || 5; - - var out = []; - pvc.stringifyRecursive(out, t, maxLevel, keyArgs); - return out.join(''); - }; - - pvc.stringifyRecursive = function(out, t, remLevels, keyArgs){ - if(remLevels > 0){ - remLevels--; - switch(typeof t){ - case 'undefined': return out.push('undefined'); - case 'object': - if(!t){ - out.push('null'); - return true; - } - - if(def.fun.is(t.stringify)){ - return t.stringify(out, remLevels, keyArgs); - } - - if(t instanceof Array){ - out.push('['); - t.forEach(function(item, index){ - if(index){ out.push(', '); } - if(!pvc.stringifyRecursive(out, item, remLevels, keyArgs)){ - out.pop(); - } - }); - out.push(']'); - } else { - var ownOnly = def.get(keyArgs, 'ownOnly', true); - if(t === def.global){ - out.push(''); - return true; - } - - if(def.fun.is(t.cloneNode)){ - // DOM object - out.push(''); - return true; - } - - if(remLevels > 1 && t.constructor !== Object){ - remLevels = 1; - ownOnly = true; - } - - out.push('{'); - var first = true; - for(var p in t){ - if(!ownOnly || def.hasOwnProp.call(t, p)){ - if(!first){ out.push(', '); } - out.push(p + ': '); - if(!pvc.stringifyRecursive(out, t[p], remLevels, keyArgs)){ - out.pop(); - if(!first){ out.pop(); } - } else if(first){ - first = false; - } - } - } - - if(first){ - var s = '' + t; - if(s !== '[object Object]'){ // not very useful - out.push('{'+ s + '}'); - } - } - - out.push('}'); - } -// else { -// out.push(JSON.stringify("'new ...'")); -// } - return true; - - case 'number': - out.push(''+(Math.round(100000 * t) / 100000)); // 6 dec places max - return true; - - case 'boolean': - out.push(''+t); - return true; - - case 'string': - out.push(JSON.stringify(t)); - return true; - - case 'function': - if(def.get(keyArgs, 'funs', false)){ - out.push(JSON.stringify(t.toString().substr(0, 13) + '...')); - return true; - } - - return false; - } - - out.push("'new ???'"); - return true; - } - }; - - pvc.orientation = { - vertical: 'vertical', - horizontal: 'horizontal' - }; - - /** - * To tag pv properties set by extension points - * @type string - * @see pvc.BaseChart#extend - */ - pvc.extensionTag = 'extension'; - - /** - * Extends a type created with {@link def.type} - * with the properties in {@link exts}, - * possibly constrained to the properties of specified names. - *

- * The properties whose values are not functions - * are converted to constant functions that return the original value. - *

- * @param {function} type - * The type to extend. - * @param {object} [exts] - * The extension object whose properties will extend the type. - * @param {string[]} [names] - * The allowed property names. - */ - pvc.extendType = function(type, exts, names){ - if(exts){ - var exts2; - var addExtension = function(ext, name){ - if(ext !== undefined){ - if(!exts2){ - exts2 = {}; - } - exts2[name] = def.fun.to(ext); - } - }; - - if(names){ - names.forEach(function(name){ - addExtension(exts[name], name); - }); - } else { - def.each(addExtension); - } - - if(exts2){ - type.add(exts2); - } - } - }; - - pv.Mark.prototype.hasDelegateValue = function(name, tag) { - var p = this.$propertiesMap[name]; - if(p){ - return (!tag || p.tag === tag); - } - - // This mimics the way #bind works - if(this.proto){ - return this.proto.hasDelegateValue(name, tag); - } - - return false; - }; - - /** - * The default color scheme used by charts. - *

- * Charts use the color scheme specified in the chart options - * {@link pvc.BaseChart#options.colors} - * and - * {@link pvc.BaseChart#options.color2AxisColorss}, - * for the main and second axis series, respectively, - * or, when any is unspecified, - * the default color scheme. - *

- *

- * When null, the color scheme {@link pv.Colors.category10} is implied. - * To obtain the default color scheme call {@link pvc.createColorScheme} - * with no arguments. - *

- *

- * To be generically useful, - * a color scheme should contain at least 10 colors. - *

- *

- * A color scheme is a function that creates a {@link pv.Scale} color scale function - * each time it is called. - * It sets as its domain the specified arguments and as range - * the pre-spcecified colors of the color scheme. - *

- * - * @readonly - * @type function - */ - pvc.defaultColorScheme = null; - - pvc.brighterColorTransform = function(color){ - return (color.rgb ? color : pv.color(color)).brighter(0.6); - }; - - /** - * Sets the colors of the default color scheme used by charts - * to a specified color array. - *

- * If null is specified, the default color scheme is reset to its original value. - *

- * - * @param {string|pv.Color|string[]|pv.Color[]|pv.Scale|function} [colors=null] Something convertible to a color scheme by {@link pvc.colorScheme}. - * @return {null|pv.Scale} A color scale function or null. - */ - pvc.setDefaultColorScheme = function(colors){ - return pvc.defaultColorScheme = pvc.colorScheme(colors); - }; - - pvc.defaultColor = pv.Colors.category10()('?'); - - /** - * Creates a color scheme if the specified argument is not one already. - * - *

- * A color scheme function is a factory of protovis color scales. - * Given the domain values, returns a protovis color scale. - * The arguments of the function are suitable for passing - * to a protovis scale's domain method. - *

- * - * @param {string|pv.Color|string[]|pv.Color[]|pv.Scale|function} [colors=null] A value convertible to a color scheme: - * a color string, - * a color object, - * an array of color strings or objects, - * a protovis color scale function, - * a color scale factory function (i.e. a color scheme), - * or null. - * - * @returns {null|function} A color scheme function or null. - */ - pvc.colorScheme = function(colors){ - if(colors == null){ - return null; - } - - if(typeof colors === 'function') { - if(!colors.hasOwnProperty('range')){ - // Assume already a color scheme (a color scale factory) - return colors; - } - - // A protovis color scale - // Obtain its range colors array and discard the scale function. - colors = colors.range(); - } else { - colors = def.array.as(colors); - } - - if(!colors.length){ - return null; - } - - return function() { - var scale = pv.colors(colors); // creates a color scale with a defined range - scale.domain.apply(scale, arguments); // defines the domain of the color scale - return scale; - }; - }, - - /** - * Creates a color scheme based on the specified colors. - * When no colors are specified, the default color scheme is returned. - * - * @see pvc.defaultColorScheme - * @param {string|pv.Color|string[]|pv.Color[]|pv.Scale|function} [colors=null] Something convertible to a color scheme by {@link pvc.colorScheme}. - * @type function - */ - pvc.createColorScheme = function(colors){ - return pvc.colorScheme(colors) || - pvc.defaultColorScheme || - pv.Colors.category10; - }; - - // Convert to Grayscale using YCbCr luminance conv. - pvc.toGrayScale = function(color, alpha, maxGrayLevel, minGrayLevel){ - color = pv.color(color); - - var avg = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b; - // Don't let the color get near white, or it becomes unperceptible in most monitors - if(maxGrayLevel === undefined) { - maxGrayLevel = 200; - } else if(maxGrayLevel == null){ - maxGrayLevel = 255; // no effect - } - - if(minGrayLevel === undefined){ - minGrayLevel = 30; - } else if(minGrayLevel == null){ - minGrayLevel = 0; // no effect - } - - var delta = (maxGrayLevel - minGrayLevel); - if(delta <= 0){ - avg = maxGrayLevel; - } else { - // Compress - avg = minGrayLevel + (avg / 255) * delta; - } - - if(alpha == null){ - alpha = color.opacity; - } else if(alpha < 0){ - alpha = (-alpha) * color.opacity; - } - - avg = Math.round(avg); - - return pv.rgb(avg, avg, avg, alpha); - }; - - // TODO: change the name of this - pvc.removeTipsyLegends = function(){ - try { - $('.tipsy').remove(); - } catch(e) { - // Do nothing - } - }; - - pvc.createDateComparer = function(parser, key){ - if(!key){ - key = pv.identity; - } - - return function(a, b){ - return parser.parse(key(a)) - parser.parse(key(b)); - }; - }; - - pvc.time = { - intervals: { - 'y': 31536e6, - - 'm': 2592e6, - 'd30': 2592e6, - - 'w': 6048e5, - 'd7': 6048e5, - - 'd': 864e5, - 'h': 36e5, - 'M': 6e4, - 's': 1e3, - 'ms': 1 - }, - - withoutTime: function(t){ - return new Date(t.getFullYear(), t.getMonth(), t.getDate()); - }, - - weekday: { - previousOrSelf: function(t, toWd){ - var wd = t.getDay(); - var difDays = wd - toWd; - if(difDays){ - // Round to the previous wanted week day - var previousOffset = difDays < 0 ? (7 + difDays) : difDays; - t = new Date(t - previousOffset * pvc.time.intervals.d); - } - return t; - }, - - nextOrSelf: function(t, toWd){ - var wd = t.getDay(); - var difDays = wd - toWd; - if(difDays){ - // Round to the next wanted week day - var nextOffset = difDays > 0 ? (7 - difDays) : -difDays; - t = new Date(t + nextOffset * pvc.time.intervals.d); - } - return t; - }, - - closestOrSelf: function(t, toWd){ - var wd = t.getDay(); // 0 - Sunday, ..., 6 - Friday - var difDays = wd - toWd; - if(difDays){ - var D = pvc.time.intervals.d; - var sign = difDays > 0 ? 1 : -1; - difDays = Math.abs(difDays); - if(difDays >= 4){ - t = new Date(t.getTime() + sign * (7 - difDays) * D); - } else { - t = new Date(t.getTime() - sign * difDays * D); - } - } - return t; - } - } - }; - - pv.Format.createParser = function(pvFormat) { - - function parse(value) { - return pvFormat.parse(value); - } - - return parse; - }; - - pv.Format.createFormatter = function(pvFormat) { - - function format(value) { - return value != null ? pvFormat.format(value) : ""; - } - - return format; - }; - - pvc.buildTitleFromName = function(name){ - // TODO: i18n - return def.firstUpperCase(name).replace(/([a-z\d])([A-Z])/, "$1 $2"); - }; - - pvc.buildIndexedId = function(prefix, index){ - if(index > 0) { - return prefix + "" + (index + 1); // base2, ortho3,..., legend2 - } - - return prefix; // base, ortho, legend - }; - - /** - * Splits an indexed id into its prefix and index. - * - * @param {string} indexedId The indexed id. - * - * @type Array - */ - pvc.splitIndexedId = function(indexedId){ - var match = /^(.*?)(\d*)$/.exec(indexedId); - var index = null; - - if(match[2]) { - index = Number(match[2]); - if(index <= 1) { - index = 1; - } else { - index--; - } - } - - return [match[1], index]; - }; - - function unwrapExtensionOne(id, prefix){ - if(id){ - if(def.object.is(id)){ - return id.abs; - } - - return prefix ? (prefix + def.firstUpperCase(id)) : id; - } - - return prefix; - } - - var oneNullArray = [null]; - - pvc.makeExtensionAbsId = function(id, prefix){ - if(!id){ - return prefix; - } - - return def - .query(prefix || oneNullArray) - .selectMany(function(oneprefix){ - return def - .query(id) - .select(function(oneid){ - return unwrapExtensionOne(oneid, oneprefix); - }); - }) - .where(def.truthy) - .array() - ; - }; - - pvc.parseDistinctIndexArray = function(value, max){ - value = def.array.as(value); - if(value == null){ - return null; - } - - if(max == null){ - max = Infinity; - } - - var a = def - .query(value) - .select(function(index){ return +index; }) // to number - .where(function(index){ return !isNaN(index) && index >= 0 && index <= max; }) - .distinct() - .array(); - - return a.length ? a : null; - }; - - pvc.parseLegendClickMode = function(clickMode){ - if(!clickMode){ - clickMode = 'none'; - } - - switch(clickMode){ - case 'toggleSelected': - case 'toggleVisible': - case 'none': - break; - - default: - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'legendClickMode' option value: '" + clickMode + "'. Assuming 'none'."); - } - - clickMode = 'none'; - break; - } - - return clickMode; - }; - - pvc.parseShape = function(shape){ - if(shape){ - switch(shape){ - case 'square': - case 'circle': - case 'diamond': - case 'triangle': - case 'cross': - case 'bar': - break; - default: - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'shape' option value: '" + shape + "'."); - } - - shape = null; - break; - } - } - - return shape; - }; - - pvc.parseContinuousColorScaleType = function(scaleType){ - if(scaleType){ - switch(scaleType){ - case 'linear': - case 'normal': - case 'discrete': - break; - - default: - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'ScaleType' option value: '" + scaleType + "'."); - } - - scaleType = null; - break; - } - } - - return scaleType; - }; - - pvc.parseDomainScope = function(scope, orientation){ - if(scope){ - switch(scope){ - case 'cell': - case 'global': - break; - - case 'section': // row (for y) or col (for x), depending on the associated orientation - if(!orientation){ - throw def.error.argumentRequired('orientation'); - } - - scope = orientation === 'y' ? 'row' : 'column'; - break; - - case 'column': - case 'row': - if(orientation && orientation !== (scope === 'row' ? 'y' : 'x')){ - scope = 'section'; - - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'DomainScope' option value: '" + scope + "' for the orientation: '" + orientation + "'."); - } - } - break; - - default: - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'DomainScope' option value: '" + scope + "'."); - } - - scope = null; - break; - } - } - - return scope; - }; - - pvc.parseDomainRoundingMode = function(mode){ - if(mode){ - switch(mode){ - case 'none': - case 'nice': - case 'tick': - break; - - default: - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'DomainRoundMode' value: '" + mode + "'."); - } - - mode = null; - break; - } - } - - return mode; - }; - - pvc.parseOverlappedLabelsMode = function(mode){ - if(mode){ - switch(mode){ - case 'leave': - case 'hide': - break; - - default: - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'OverlappedLabelsMode' option value: '" + mode + "'."); - } - - mode = null; - break; - } - } - - return mode; - }; - - pvc.castNumber = function(value) { - if(value != null) { - value = +value; // to number - if(isNaN(value)) { - value = null; - } - } - - return value; - }; - - pvc.parseWaterDirection = function(value) { - if(value){ - switch(value){ - case 'up': - case 'down': - return value; - } - - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'WaterDirection' value: '" + value + "'."); - } - } - }; - - pvc.parseTrendType = function(value) { - if(value){ - if(value === 'none'){ - return value; - } - - if(pvc.trends.has(value)){ - return value; - } - - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'TrendType' value: '" + value + "'."); - } - } - }; - - pvc.parseNullInterpolationMode = function(value) { - if(value){ - switch(value){ - case 'none': - case 'linear': - case 'zero': - return value; - } - - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'NullInterpolationMode' value: '" + value + "'."); - } - } - }; - - pvc.parseAlign = function(side, align){ - var align2, isInvalid; - if(side === 'left' || side === 'right'){ - align2 = align && pvc.BasePanel.verticalAlign[align]; - if(!align2){ - align2 = 'middle'; - isInvalid = !!align; - } - } else { - align2 = align && pvc.BasePanel.horizontalAlign[align]; - if(!align2){ - align2 = 'center'; - isInvalid = !!align; - } - } - - if(isInvalid && pvc.debug >= 2){ - pvc.log(def.format("Invalid alignment value '{0}'. Assuming '{1}'.", [align, align2])); - } - - return align2; - }; - - // suitable for protovis.anchor(..) of all but the Wedge mark... - pvc.parseAnchor = function(anchor){ - if(anchor){ - switch(anchor){ - case 'top': - case 'left': - case 'center': - case 'bottom': - case 'right': - return anchor; - } - - if(pvc.debug >= 2){ - pvc.log(def.format("Invalid anchor value '{0}'.", [anchor])); - } - } - }; - - pvc.parseAnchorWedge = function(anchor){ - if(anchor){ - switch(anchor){ - case 'outer': - case 'inner': - case 'center': - case 'start': - case 'end': - return anchor; - } - - if(pvc.debug >= 2){ - pvc.log(def.format("Invalid wedge anchor value '{0}'.", [anchor])); - } - } - }; - - pvc.unionExtents = function(result, range){ - if(!result) { - if(!range){ - return null; - } - - result = {min: range.min, max: range.max}; - } else if(range){ - if(range.min < result.min){ - result.min = range.min; - } - - if(range.max > result.max){ - result.max = range.max; - } - } - - return result; - }; - - /** - * Creates a margins/sides object. - * @constructor - * @param {string|number|object} sides May be a css-like shorthand margin string. - * - *
    - *
  1. "1" - {all: '1'}
  2. - *
  3. "1 2" - {top: '1', left: '2', right: '2', bottom: '1'}
  4. - *
  5. "1 2 3" - {top: '1', left: '2', right: '2', bottom: '3'}
  6. - *
  7. "1 2 3 4" - {top: '1', right: '2', bottom: '3', left: '4'}
  8. - *
- */ - pvc.Sides = function(sides){ - if(sides != null){ - this.setSides(sides); - } - }; - - pvc.Sides.hnames = 'left right'.split(' '); - pvc.Sides.vnames = 'top bottom'.split(' '); - pvc.Sides.names = 'left right top bottom'.split(' '); - pvc.Sides.namesSet = pv.dict(pvc.Sides.names, def.retTrue); - - pvc.parsePosition = function(side, defaultSide){ - if(side && !def.hasOwn(pvc.Sides.namesSet, side)){ - if(!defaultSide){ - defaultSide = 'left'; - } - - if(pvc.debug >= 2){ - pvc.log(def.format("Invalid position value '{0}. Assuming '{1}'.", [side, defaultSide])); - } - - side = defaultSide; - } - - return side; - }; - - pvc.Sides.as = function(v){ - if(v != null && !(v instanceof pvc.Sides)){ - v = new pvc.Sides().setSides(v); - } - - return v; - }; - - pvc.Sides.prototype.stringify = function(out, remLevels, keyArgs){ - return pvc.stringifyRecursive(out, def.copyOwn(this), remLevels, keyArgs); - }; - - pvc.Sides.prototype.setSides = function(sides){ - if(typeof sides === 'string'){ - var comps = sides.split(/\s+/).map(function(comp){ - return pvc.PercentValue.parse(comp); - }); - - switch(comps.length){ - case 1: - this.set('all', comps[0]); - return this; - - case 2: - this.set('top', comps[0]); - this.set('left', comps[1]); - this.set('right', comps[1]); - this.set('bottom', comps[0]); - return this; - - case 3: - this.set('top', comps[0]); - this.set('left', comps[1]); - this.set('right', comps[1]); - this.set('bottom', comps[2]); - return this; - - case 4: - this.set('top', comps[0]); - this.set('right', comps[1]); - this.set('bottom', comps[2]); - this.set('left', comps[3]); - return this; - - case 0: - return this; - } - } else if(typeof sides === 'number') { - this.set('all', sides); - return this; - } else if (typeof sides === 'object') { - if(sides instanceof pvc.PercentValue){ - this.set('all', sides); - } else { - this.set('all', sides.all); - for(var p in sides){ - if(p !== 'all' && pvc.Sides.namesSet.hasOwnProperty(p)){ - this.set(p, sides[p]); - } - } - } - - return this; - } - - if(pvc.debug) { - pvc.log("Invalid 'sides' value: " + pvc.stringify(sides)); - } - - return this; - }; - - pvc.Sides.prototype.set = function(prop, value){ - value = pvc.PercentValue.parse(value); - if(value != null){ - if(prop === 'all'){ - // expand - pvc.Sides.names.forEach(function(p){ - this[p] = value; - }, this); - - } else if(def.hasOwn(pvc.Sides.namesSet, prop)){ - this[prop] = value; - } - } - }; - - pvc.Sides.prototype.resolve = function(width, height){ - if(typeof width === 'object'){ - height = width.height; - width = width.width; - } - - var sides = {}; - - pvc.Sides.names.forEach(function(side){ - var value = 0; - var sideValue = this[side]; - if(sideValue != null){ - if(typeof(sideValue) === 'number'){ - value = sideValue; - } else { - value = sideValue.resolve((side === 'left' || side === 'right') ? width : height); - } - } - - sides[side] = value; - }, this); - - return pvc.Sides.updateSize(sides); - }; - - pvc.Sides.updateSize = function(sides){ - sides.width = (sides.left || 0) + (sides.right || 0); - sides.height = (sides.bottom || 0) + (sides.top || 0); - - return sides; - }; - - pvc.Sides.resolvedMax = function(a, b){ - var sides = {}; - - pvc.Sides.names.forEach(function(side){ - sides[side] = Math.max(a[side] || 0, b[side] || 0); - }); - - return sides; - }; - - pvc.Sides.inflate = function(sides, by){ - var sidesOut = {}; - - pvc.Sides.names.forEach(function(side){ - sidesOut[side] = (sides[side] || 0) + by; - }); - - return pvc.Sides.updateSize(sidesOut); - }; - - // ------------- - - pvc.PercentValue = function(pct){ - this.percent = pct; - }; - - pvc.PercentValue.prototype.resolve = function(total){ - return this.percent * total; - }; - - pvc.PercentValue.parse = function(value){ - if(value != null && value !== ''){ - switch(typeof value){ - case 'number': return value; - case 'string': - var match = value.match(/^(.+?)\s*(%)?$/); - if(match){ - var n = +match[1]; - if(!isNaN(n)){ - if(match[2]){ - if(n >= 0){ - return new pvc.PercentValue(n / 100); - } - } else { - return n; - } - } - } - break; - - case 'object': - if(value instanceof pvc.PercentValue){ - return value; - } - break; - } - - if(pvc.debug){ - pvc.log(def.format("Invalid margins component '{0}'", [''+value])); - } - } - }; - - pvc.PercentValue.resolve = function(value, total){ - return (value instanceof pvc.PercentValue) ? value.resolve(total) : value; - }; - - /* Z-Order */ - - // Backup original methods - var markRenderCore = pv.Mark.prototype.renderCore, - markZOrder = pv.Mark.prototype.zOrder; - - pv.Mark.prototype.zOrder = function(zOrder) { - var borderPanel = this.borderPanel; - if(borderPanel && borderPanel !== this){ - return markZOrder.call(borderPanel, zOrder); - } - - return markZOrder.call(this, zOrder); - }; - - /* Render id */ - pv.Mark.prototype.renderCore = function(){ - /* Assign a new render id to the root mark */ - var root = this.root; - - root._renderId = (root._renderId || 0) + 1; - - if(pvc.debug >= 25){ - pvc.log("BEGIN RENDER " + root._renderId); - } - - /* Render */ - markRenderCore.apply(this, arguments); - - if(pvc.debug >= 25){ - pvc.log("END RENDER " + root._renderId); - } - }; - - pv.Mark.prototype.renderId = function(){ - return this.root._renderId; - }; - - /* PROPERTIES */ - pv.Mark.prototype.wrapper = function(wrapper){ - this._wrapper = wrapper; - - return this; - }; - - pv.Mark.prototype.wrap = function(f, m){ - if(f && def.fun.is(f) && this._wrapper && !f._cccWrapped){ - f = this._wrapper(f, m); - - f._cccWrapped = true; - } - - return f; - }; - - pv.Mark.prototype.lock = function(prop, value){ - if(value !== undefined){ - this[prop](value); - } - - (this._locked || (this._locked = {}))[prop] = true; - - return this; - }; - - pv.Mark.prototype.isIntercepted = function(prop){ - return this._intercepted && this._intercepted[prop]; - }; - - pv.Mark.prototype.isLocked = function(prop){ - return this._locked && this._locked[prop]; - }; - - /* ANCHORS */ - /** - * name = left | right | top | bottom - */ - pv.Mark.prototype.addMargin = function(name, margin) { - if(margin !== 0){ - var staticValue = def.nullyTo(this.propertyValue(name), 0), - fMeasure = pv.functor(staticValue); - - this[name](function(){ - return margin + fMeasure.apply(this, arraySlice.call(arguments)); - }); - } - - return this; - }; - - /** - * margins = { - * all: - * left: - * right: - * top: - * bottom: - * } - */ - pv.Mark.prototype.addMargins = function(margins) { - var all = def.get(margins, 'all', 0); - - this.addMargin('left', def.get(margins, 'left', all)); - this.addMargin('right', def.get(margins, 'right', all)); - this.addMargin('top', def.get(margins, 'top', all)); - this.addMargin('bottom', def.get(margins, 'bottom', all)); - - return this; - }; - - /* SCENE */ - pv.Mark.prototype.eachInstanceWithData = function(fun, ctx){ - this.eachInstance(function(scenes, index, t){ - if(scenes.mark.sign && scenes[index].data){ - fun.call(ctx, scenes, index, t); - } - }); - }; - - /* BOUNDS */ - pv.Transform.prototype.transformHPosition = function(left){ - return this.x + (this.k * left); - }; - - pv.Transform.prototype.transformVPosition = function(top){ - return this.y + (this.k * top); - }; - - // width / height - pv.Transform.prototype.transformLength = function(length){ - return this.k * length; - }; - - // -------------------- - - var Size = def.type('pvc.Size') - .init(function(width, height){ - if(arguments.length === 1){ - if(width != null){ - this.setSize(width); - } - } else { - if(width != null){ - this.width = width; - } - - if(height != null){ - this.height = height; - } - } - }) - .add({ - stringify: function(out, remLevels, keyArgs){ - return pvc.stringifyRecursive(out, def.copyOwn(this), remLevels, keyArgs); - }, - - setSize: function(size, keyArgs){ - if(typeof size === 'string'){ - var comps = size.split(/\s+/).map(function(comp){ - return pvc.PercentValue.parse(comp); - }); - - switch(comps.length){ - case 1: - this.set(def.get(keyArgs, 'singleProp', 'all'), comps[0]); - return this; - - case 2: - this.set('width', comps[0]); - this.set('height', comps[1]); - return this; - - case 0: - return this; - } - } else if(typeof size === 'number') { - this.set(def.get(keyArgs, 'singleProp', 'all'), size); - return this; - } else if (typeof size === 'object') { - if(size instanceof pvc.PercentValue){ - this.set(def.get(keyArgs, 'singleProp', 'all'), size); - } else { - - this.set('all', size.all); - for(var p in size){ - if(p !== 'all'){ - this.set(p, size[p]); - } - } - } - return this; - } - - if(pvc.debug) { - pvc.log("Invalid 'size' value: " + pvc.stringify(size)); - } - - return this; - }, - - set: function(prop, value){ - if(value != null && (prop === 'all' || def.hasOwn(pvc.Size.namesSet, prop))){ - value = pvc.PercentValue.parse(value); - if(value != null){ - if(prop === 'all'){ - // expand - pvc.Size.names.forEach(function(p){ - this[p] = value; - }, this); - - } else { - this[prop] = value; - } - } - } - - return this; - }, - - clone: function(){ - return new Size(this.width, this.height); - }, - - intersect: function(size){ - return new Size( - Math.min(this.width, size.width), - Math.min(this.height, size.height)); - }, - - resolve: function(refSize){ - var size = {}; - - pvc.Size.names.forEach(function(length){ - var lengthValue = this[length]; - if(lengthValue != null){ - if(typeof(lengthValue) === 'number'){ - size[length] = lengthValue; - } else if(refSize){ - var refLength = refSize[length]; - if(refLength != null){ - size[length] = lengthValue.resolve(refLength); - } - } - } - }, this); - - return size; - } - }); - - pvc.Size.names = ['width', 'height']; - pvc.Size.namesSet = pv.dict(pvc.Size.names, def.retTrue); - - pvc.Size.toOrtho = function(value, anchor){ - if(value != null){ - // Single size (a number or a string with only one number) - // should be interpreted as meaning the orthogonal length. - var a_ol; - if(anchor){ - a_ol = pvc.BasePanel.orthogonalLength[anchor]; - } - - value = pvc.Size.to(value, {singleProp: a_ol}); - - if(anchor){ - delete value[pvc.BasePanel.oppositeLength[a_ol]]; - } - } - - return value; - }; - - pvc.Size.to = function(v, keyArgs){ - if(v != null && !(v instanceof Size)){ - v = new Size().setSize(v, keyArgs); - } - - return v; - }; - - // -------------------- - - var Offset = def.type('pvc.Offset') - .init(function(x, y){ - if(arguments.length === 1){ - if(x != null){ - this.setOffset(x); - } - } else { - if(x != null){ - this.x = x; - } - - if(y != null){ - this.y = y; - } - } - }) - .add({ - stringify: function(out, remLevels, keyArgs){ - return pvc.stringifyRecursive(out, def.copyOwn(this), remLevels, keyArgs); - }, - - setOffset: function(offset, keyArgs){ - if(typeof offset === 'string'){ - var comps = offset.split(/\s+/).map(function(comp){ - return pvc.PercentValue.parse(comp); - }); - - switch(comps.length){ - case 1: - this.set(def.get(keyArgs, 'singleProp', 'all'), comps[0]); - return this; - - case 2: - this.set('x', comps[0]); - this.set('y', comps[1]); - return this; - - case 0: - return this; - } - } else if(typeof offset === 'number') { - this.set(def.get(keyArgs, 'singleProp', 'all'), offset); - return this; - } else if (typeof offset === 'object') { - this.set('all', offset.all); - for(var p in offset){ - if(p !== 'all'){ - this.set(p, offset[p]); - } - } - return this; - } - - if(pvc.debug) { - pvc.log("Invalid 'offset' value: " + pvc.stringify(offset)); - } - return this; - }, - - set: function(prop, value){ - if(value != null && def.hasOwn(pvc.Offset.namesSet, prop)){ - value = pvc.PercentValue.parse(value); - if(value != null){ - if(prop === 'all'){ - // expand - pvc.Offset.names.forEach(function(p){ - this[p] = value; - }, this); - - } else { - this[prop] = value; - } - } - } - }, - - resolve: function(refSize){ - var offset = {}; - - pvc.Size.names.forEach(function(length){ - var offsetProp = pvc.Offset.namesSizeToOffset[length]; - var offsetValue = this[offsetProp]; - if(offsetValue != null){ - if(typeof(offsetValue) === 'number'){ - offset[offsetProp] = offsetValue; - } else if(refSize){ - var refLength = refSize[length]; - if(refLength != null){ - offset[offsetProp] = offsetValue.resolve(refLength); - } - } - } - }, this); - - return offset; - } - }); - - pvc.Offset.names = ['x', 'y']; - pvc.Offset.namesSet = pv.dict(pvc.Offset.names, def.retTrue); - pvc.Offset.namesSizeToOffset = {width: 'x', height: 'y'}; - pvc.Offset.namesSidesToOffset = {left: 'x', right: 'x', top: 'y', bottom: 'y'}; - - pvc.Offset.as = function(v){ - if(v != null && !(v instanceof Offset)){ - v = new Offset().setOffset(v); - } - - return v; - }; - -}()); // End private scope - -/** - * Implements support for svg detection - */ -(function($){ - /*global document:true */ - $.support.svg = $.support.svg || - document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"); -}(/*global jQuery:true */jQuery)); diff --git a/pacotes/ccc2/pvc/pvc.options.js b/pacotes/ccc2/pvc/pvc.options.js deleted file mode 100755 index c7b7d60..0000000 --- a/pacotes/ccc2/pvc/pvc.options.js +++ /dev/null @@ -1,433 +0,0 @@ - -// Options management utility -def.scope(function(){ - /** - * Creates an options manager given an options specification object, - * and, optionally, a corresponding context object. - * - * @name pvc.options - * @class An options manager. - * @example - *
-     * var foo = {};
-     * 
-     * foo.options = pvc.options({
-     *         Name: {
-     *             alias: 'legendName',
-     *             cast:  String,
-     *             value: 'John Doe',
-     *             resolve: function(context){
-     *                 this.setDefault();
-     *             }
-     *         }
-     *     }, foo);
-     *     
-     * foo.options.specify({
-     *    'legendName': "Fritz"
-     * });
-     * 
-     * foo.options('Name2'); // -> "Fritz"
-     * 
- * - * @constructor - * @param {object} specs An object whose properties, owned or inherited, - * have the name of an option to define, and whose values are option - * specification objects, each having the following optional properties: - *
    - *
  • resolve - - * a method that allows to apply custom value resolution logic for an option. - * - * It is called - * on the {@link pvc.options.Info} instance with the - * previously specified context object as argument. - *
  • - *
  • cast - a cast function, called to normalize the value of an option
  • - *
  • value - the default value of the property, considered already cast
  • - * - *
- * - * @param {object} [context=null] Optional context object on which to call - * the 'resolve' function specified in {@link specs}. - * - * @type function - */ - function options(specs, context){ - /*jshint expr:true */ - specs || def.fail.argumentRequired('specs'); - - var _infos = {}; - - def.each(specs, function(spec, name){ - var info = new OptionInfo(name, option, context, spec); - _infos[info.name] = info; - }); - - /** @private */ - function resolve(name){ - var info = def.getOwn(_infos, name) || - def.fail.operationInvalid("Undefined option '{0}'", [name]); - - return info.resolve(); - } - - /** - * Obtains the value of an option given its name. - *

- * If a value for the option hasn't been provided - * a default value is returned, - * from the option specification. - *

- * @name pvc.options#option - * @function - * @param {string} name The name of the option. - * @param {booleam} [noDefault=false] Prevents returning a default value. - * If a value for the option hasn't been provided, undefined is returned. - * - * @type any - */ - function option(name, noDefault){ - var info = resolve(name); - return noDefault && !info.isSpecified ? undefined : info.value; - } - - /** - * Indicates if a value for a given option has been specified. - * @name pvc.options#isSpecified - * @function - * @param {string} name The name of the option. - * @type boolean - */ - function isSpecified(name){ - return resolve(name).isSpecified; - } - - /** - * Obtains the value of an option given its name, - * but only if it has been specified (not defaulted). - *

- * This is a convenience method for calling {@link #option} - * with the noDefault argument with the value true. - *

- * - * @name pvc.options#specified - * @function - * @param {string} name The name of the option. - * - * @type any - */ - function specified(name){ - return option(name, /*noDefault*/ true); - } - - /** - * Indicates if an option with the given name is defined. - * @name pvc.options#isDefined - * @function - * @param {string} name The name of the option. - * @type boolean - */ - function isDefined(name){ - return def.hasOwn(_infos, name); - } - - /** - * Specifies options' values given an object - * with properties as option names - * and values as option values. - *

- * Only properties whose name is the name of a defined option - * are taken into account. - *

- *

- * Every property, own or inherited, is considered, - * as long as its value is not undefined. - *

- * @name pvc.options#specify - * @function - * @param {object} [opts] An object with option values - * @returns {function} The options manager. - */ - function specify(opts){ - return set(opts, false); - } - - /** - * Sets options' default values. - * @name pvc.options#defaults - * @function - * @param {object} [opts] An object with option default values - * @returns {function} The options manager. - * @see #specify - */ - function defaults(opts){ - return set(opts, true); - } - - /** - * Obtains the default value of an option, given its name. - *

- * If a property has no default value, undefined is returned. - *

- * @name pvc.options#defaultValue - * @function - * @param {string} name The name of the option. - */ - function getDefaultValue(name){ - return resolve(name)._defaultValue; - } - - /** @private */ - function set(opts, isDefault){ - for(var name in opts){ - var info = def.getOwn(_infos, name); - if(info){ - var value = opts[name]; - if(value !== undefined){ - info.set(value, isDefault); - } - } - } - - return option; - } - - // ------------ - - option.option = option; - option.specified = specified; - option.isSpecified = isSpecified; - option.isDefined = isDefined; - - option.defaultValue = getDefaultValue; - - option.specify = specify; - option.defaults = defaults; - - return option; - } - - // ------------ - - // Creates a resolve method, - // that combines a list of resolvers. - // The resolve stops when the first resolver returns the value true, - // returning true as well. - function resolvers(list){ - return function(optionInfo){ - for(var i = 0, L = list.length ; i < L ; i++){ - var m = list[i]; - - if(def.string.is(m)){ - m = this[m]; - } - - if(m.call(this, optionInfo) === true){ - return true; - } - } - }; - } - - function constantResolver(value, op){ - return function(optionInfo){ - optionInfo.specify(value); - return true; - }; - } - - function specifyResolver(fun, op){ - return function(optionInfo){ - var value = fun.call(this, optionInfo); - if(value !== undefined){ - optionInfo.specify(value); - return true; - } - }; - } - - function defaultResolver(fun){ - return function(optionInfo){ - var value = fun.call(this, optionInfo); - if(value !== undefined){ - optionInfo.defaultValue(value); - return true; - } - }; - } - - options.resolvers = resolvers; - options.constant = constantResolver; - options.specify = specifyResolver; - options.defaultValue = defaultResolver; - - // ------------ - - pvc.options = options; - - // ------------ - - /** - * @name pvc.options.Info - * @class An option in an options manager. - */ - var OptionInfo = def.type() - .init(function(name, option, context, spec){ - this.name = name; - - this._context = context; - this.option = option; - - this._cast = def.get(spec, 'cast'); - - // Assumed already cast - // May be undefined - var value = def.get(spec, 'value'); - if(value !== undefined){ - this._defaultValue = this.value = value; - } - - this.resolveCore = def.get(spec, 'resolve'); - if(!this.resolveCore){ - this.isResolved = true; - } - - var getDefault = def.get(spec, 'getDefault'); - if(getDefault){ - this._getDefault = getDefault; - } - - var data = def.get(spec, 'data'); - if(data != null){ - this.data = data; - } - - // -------- - // Can be used by resolvers... - this.alias = def.array.to(def.get(spec, 'alias')); - }) - .add( /** @lends pvc.options.Info# */{ - isSpecified: false, - isResolved: false, - value: undefined, - - /** @private */ - _defaultValue: undefined, - - /** - * Resolves an option if it is not yet resolved. - * @type pvc.options.Info - */ - resolve: function(){ - if(!this.isResolved){ - // In case of re-entry, the initial default value is obtained. - this.isResolved = true; - - var resolve = this._getFunProp('resolveCore'); - - // Must call set, specify or defaultValue - // Or the current default value becomes the value. - resolve.call(this._context, this); - - if(this.value == null){ - var getDefault = this._getFunProp('_getDefault'); - if(getDefault){ - var value = this.cast(getDefault.call(this._context, this)); - if(value != null){ - delete this.isSpecified; - this.value = this._defaultValue = value; - } - } - } - } - - return this; - }, - - /** - * Specifies the value of the option. - * - * @param {any} value the option value. - * @type pvc.options.Info - */ - specify: function(value){ - return this.set(value, false); - }, - - /** - * Gets, and optionally sets, the default value. - * @param {any} [value=undefined] the option default value. - * @type any - */ - defaultValue: function(defaultValue){ - if(defaultValue !== undefined){ - this.set(defaultValue, true); - } - - return this._defaultValue; - }, - - cast: function(value){ - if(value != null){ - var cast = this._getFunProp('_cast'); - if(cast){ - value = cast.call(this._context, value, this); - } - } - return value; - }, - - dynDefault: function(){ - var dynDefault = this._getFunProp('_dynDefault'); - if(dynDefault){ - return this.cast(dynDefault.call(this._context, this)); - } - }, - - /** - * Sets the option's value or default value. - * - * @param {any} [value=undefined] the option value or default value. - * @param {boolean} [isDefault=false] indicates if the operation sets the default value. - * - * @type pvc.options.Info - */ - set: function(value, isDefault){ - if(value != null){ - value = this.cast(value); - } - - if(value == null){ - value = this.dynDefault(); - if(value != null){ - isDefault = true; - } - } - - if(!isDefault){ - this.isSpecified = true; - this.isResolved = true; - this.value = value; - } else { - this._defaultValue = value; - - // Don't touch an already specified value - if(!this.isSpecified){ - this.value = value; - } - } - - return this; - }, - - _getFunProp: function(name){ - var fun = this[name]; - if(fun){ - var context = this._context; - if(context && def.string.is(fun)){ - fun = context[fun]; - } - } - return fun; - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvc.text.js b/pacotes/ccc2/pvc/pvc.text.js deleted file mode 100755 index 6f18bcb..0000000 --- a/pacotes/ccc2/pvc/pvc.text.js +++ /dev/null @@ -1,120 +0,0 @@ - -pvc.text = { - getFitInfo: function(w, h, text, font, diagMargin){ - if(text === '') { - return {h: true, v: true, d: true}; - } - - var len = pv.Text.measure(text, font).width; - return { - h: len <= w, - v: len <= h, - d: len <= Math.sqrt(w*w + h*h) - diagMargin - }; - }, - - trimToWidthB: function(len, text, font, trimTerminator, before){ - len -= pv.Text.measure(trimTerminator, font).width; - - return pvc.text.trimToWidth(len, text, font, trimTerminator, before); - }, - - trimToWidth: function(len, text, font, trimTerminator, before){ - if(text === '') { - return text; - } - - var textLen = pv.Text.measure(text, font).width; - if(textLen <= len){ - return text; - } - - if(textLen > len * 1.5){ //cutoff for using other algorithm - return pvc.text.trimToWidthBin(len, text, font, trimTerminator, before); - } - - while(textLen > len){ - text = before ? text.slice(1) : text.slice(0, text.length -1); - textLen = pv.Text.measure(text, font).width; - } - - return before ? (trimTerminator + text) : (text + trimTerminator); - }, - - trimToWidthBin: function(len, text, font, trimTerminator, before){ - - var ilen = text.length, - high = ilen - 2, - low = 0, - mid, - textLen; - - while(low <= high && high > 0){ - - mid = Math.ceil((low + high)/2); - - var textMid = before ? text.slice(ilen - mid) : text.slice(0, mid); - textLen = pv.Text.measure(textMid, font).width; - if(textLen > len){ - high = mid - 1; - } else if(pv.Text.measure(before ? text.slice(ilen - mid - 1) : text.slice(0, mid + 1), font).width < len){ - low = mid + 1; - } else { - return before ? (trimTerminator + textMid) : (textMid + trimTerminator); - } - } - - return before ? (trimTerminator + text.slice(ilen - high)) : (text.slice(0, high) + trimTerminator); - }, - - justify: function(text, lineWidth, font){ - var lines = []; - - if(lineWidth < pv.Text.measure('a', font).width){ - // Not even one letter fits... - return lines; - } - - var words = (text || '').split(/\s+/); - - var line = ""; - while(words.length){ - var word = words.shift(); - if(word){ - var nextLine = line ? (line + " " + word) : word; - if(pv.Text.measure(nextLine, font).width > lineWidth){ - // The word by itself may overflow the line width - - // Start new line - if(line){ - lines.push(line); - } - - line = word; - } else { - line = nextLine; - } - } - } - - if(line){ - lines.push(line); - } - - return lines; - }, - - /* Returns a label's BBox relative to its anchor point */ - getLabelBBox: function(textWidth, textHeight, align, baseline, angle, margin){ - - var polygon = pv.Label.getPolygon(textWidth, textHeight, align, baseline, angle, margin); - - var bbox = polygon.bbox(); - bbox.source = polygon; - bbox.sourceAngle = angle; - bbox.sourceAlign = align; - bbox.sourceTextWidth = textWidth; - - return bbox; - } -}; diff --git a/pacotes/ccc2/pvc/pvc.trends.js b/pacotes/ccc2/pvc/pvc.trends.js deleted file mode 100755 index 287ca36..0000000 --- a/pacotes/ccc2/pvc/pvc.trends.js +++ /dev/null @@ -1,208 +0,0 @@ -def.space('pvc.trends', function(trends){ - var _trends = {}; - - def.set(trends, - 'define', function(type, trendSpec){ - /*jshint expr:true*/ - - type || def.fail.argumentRequired('type'); - trendSpec || def.fail.argumentRequired('trendSpec'); - def.object.is(trendSpec) || def.fail.argumentInvalid('trendSpec', "Must be a trend specification object."); - - if(pvc.debug >= 2 && def.hasOwn(_trends, type)){ - pvc.log(def.format("[WARNING] A trend type with the name '{0}' is already defined.", [type])); - } - - var label = trendSpec.label || def.fail.argumentRequired('trendSpec.label'); - var model = trendSpec.model || def.fail.argumentRequired('trendSpec.model'); - def.fun.is(model) || def.fail.argumentInvalid('trendSpec.mode', "Must be a function."); - - var trendInfo = { - dataPartAtom: {v: 'trend', f: label}, - type: type, - label: label, - model: model - }; - - _trends[type] = trendInfo; - }, - - 'get', function(type){ - /*jshint expr:true*/ - type || def.fail.argumentRequired('type'); - return def.getOwn(_trends, type) || - def.fail.operationInvalid("Undefined trend type '{0}'.", [type]); - }, - - 'has', function(type){ - return def.hasOwn(_trends, type); - }, - - 'types', function(){ - return def.ownKeys(_trends); - }); - - - trends.define('linear', { - label: 'Linear trend', - model: function(options){ - var rows = def.get(options, 'rows'); - var funX = def.get(options, 'x'); - var funY = def.get(options, 'y'); - - var i = 0; - var N = 0; - var sumX = 0; - var sumY = 0; - var sumXY = 0; - var sumXX = 0; - var parseNum = function(value){ - return value != null ? (+value) : NaN; // to Number works for dates as well - }; - - while(rows.next()){ - var row = rows.item; - - // Ignore null && NaN values - - var x = funX ? parseNum(funX(row)) : i; // use the index itself for discrete stuff - if(!isNaN(x)){ - var y = parseNum(funY(row)); - if(!isNaN(y)){ - N++; - - sumX += x; - sumY += y; - sumXY += x * y; - sumXX += x * x; - } - } - - i++; // Discrete nulls must still increment the index - } - - // y = alpha + beta * x - var alpha, beta; - if(N >= 2){ - var avgX = sumX / N; - var avgY = sumY / N; - var avgXY = sumXY / N; - var avgXX = sumXX / N; - - // When N === 1 => den = 0 - var den = (avgXX - avgX * avgX); - if(den === 0){ - beta = 0; - } else { - beta = (avgXY - (avgX * avgY)) / den; - } - - alpha = avgY - beta * avgX; - - return { - alpha: alpha, - beta: beta, - - reset: def.noop, - - // y = alpha + beta * x - sample: function(x/*, y, i*/){ - return alpha + beta * (+x); - } - }; - } - } - }); - - // Source: http://en.wikipedia.org/wiki/Moving_average - trends.define('moving-average', { - label: 'Moving average', - model: function(options){ - var W = Math.max(+(def.get(options, 'periods') || 3), 2); - - var sum = 0; // Current sum of values in avgValues - var avgValues = []; // Values in the average window - - return { - reset: function(){ - sum = 0; - avgValues.length = 0; - }, - - sample: function(x, y, i){ - // Only y is relevant for this trend type - var L = W; - if(y != null){ - avgValues.unshift(y); - sum += y; - - L = avgValues.length; - if(L > W){ - sum -= avgValues.pop(); - L = W; - } - } - - return sum / L; - } - }; - } - }); - - // Source: http://en.wikipedia.org/wiki/Moving_average - trends.define('weighted-moving-average', { - label: 'Weighted Moving average', - model: function(options){ - var W = Math.max(+(def.get(options, 'periods') || 3), 2); - - // Current sum of values in the window - var sum = 0; // Current sum of values in avgValues - - // Current numerator - var numer = 0; - - var avgValues = []; // Values in the average window - var L = 0; - - // Constant Denominator (from L = W onward it is constant) - // W + (W - 1) + ... + 2 + 1 - // = W * (W + 1) / 2; - var denom = 0; - - return { - reset: function(){ - sum = numer = denom = L = 0; - avgValues.length = 0; - }, - - sample: function(x, y/*, i*/){ - // Only y is relevant for this trend type - if(y != null){ - - if(L < W){ - // Still filling the avgValues array - - avgValues.push(y); - L++; - denom += L; - numer += L * y; - sum += y; - } else { - // denom is now equal to: W * (W + 1) / 2; - numer += (L * y) - sum; - sum += y - avgValues[0]; // newest - oldest - - // Shift avgValues left - for(var j = 1 ; j < W ; j++){ - avgValues[j - 1] = avgValues[j]; - } - avgValues[W - 1] = y; - } - } - - return numer / denom; - } - }; - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcAbstract.js b/pacotes/ccc2/pvc/pvcAbstract.js deleted file mode 100755 index 1359e29..0000000 --- a/pacotes/ccc2/pvc/pvcAbstract.js +++ /dev/null @@ -1,52 +0,0 @@ -def -.type('pvc.Abstract') -.init(function(){ - this._syncLog(); -}) -.add({ - invisibleLineWidth: 0.001, - defaultLineWidth: 1.5, - - _logInstanceId: null, - - _syncLog: function(){ - if (pvc.debug && typeof console !== "undefined"){ - var logId = this._getLogInstanceId(); - - ['log', 'info', ['trace', 'debug'], 'error', 'warn', 'group', 'groupEnd'].forEach(function(ps){ - ps = ps instanceof Array ? ps : [ps, ps]; - - pvc._installLog(this, '_' + ps[0], ps[1], logId); - }, this); - } - }, - - _getLogInstanceId: function(){ - return this._logInstanceId || - (this._logInstanceId = this._processLogInstanceId(this._createLogInstanceId())); - }, - - _createLogInstanceId: function(){ - return '' + this.constructor; - }, - - _processLogInstanceId: function(logInstanceId){ - var L = 30; - var s = logInstanceId.substr(0, L); - if(s.length < L){ - s += def.array.create(L - s.length, ' ').join(''); - } - - return "[" + s + "]"; - } -}); - -def.scope(function(){ - var o = pvc.Abstract.prototype; - var syncLogHook = function(){ this._syncLog(); }; - - ['log', 'info', 'trace', 'error', 'warn', 'group', 'groupEnd'].forEach(function(p){ - o['_' + p] = syncLogHook; - }); -}); - diff --git a/pacotes/ccc2/pvc/pvcAxisPanel.js b/pacotes/ccc2/pvc/pvcAxisPanel.js deleted file mode 100755 index 81e2517..0000000 --- a/pacotes/ccc2/pvc/pvcAxisPanel.js +++ /dev/null @@ -1,1664 +0,0 @@ - -/** - * AxisPanel panel. - */ -def -.type('pvc.AxisPanel', pvc.BasePanel) -.init(function(chart, parent, axis, options) { - options = def.create(options, { - anchor: axis.option('Position') - }); - var anchor = options.anchor || this.anchor; - - // Prevent the border from affecting the box model, - // providing a static 0 value, independently of the actual drawn value... - //this.borderWidth = 0; - - this.axis = axis; // must be set before calling base, because of log id - - this.base(chart, parent, options); - - - this.roleName = axis.role.name; - this.isDiscrete = axis.role.isDiscrete(); - this._extensionPrefix = axis.extensionPrefixes; - - if(this.labelSpacingMin == null){ - // The user tolerance for "missing" stuff is much smaller with discrete stuff - this.labelSpacingMin = this.isDiscrete ? 0.1 : 1.5; // em - } - - if(this.showTicks == null){ - this.showTicks = !this.isDiscrete; - } - - if(options.font === undefined){ - var extFont = this._getConstantExtension('label', 'font'); - if(extFont){ - this.font = extFont; - } - } - - if(options.tickLength === undefined){ - // height or width - var tickLength = +this._getConstantExtension('ticks', this.anchorOrthoLength(anchor)); - if(!isNaN(tickLength) && isFinite(tickLength)){ - this.tickLength = tickLength; - } - } -}) -.add({ - pvRule: null, - pvTicks: null, - pvLabel: null, - pvRuleGrid: null, - pvScale: null, - - isDiscrete: false, - roleName: null, - axis: null, - anchor: "bottom", - tickLength: 6, - - scale: null, - ruleCrossesMargin: true, - font: '9px sans-serif', // label font - labelSpacingMin: null, - // To be used in linear scales - domainRoundMode: 'none', - desiredTickCount: null, - tickExponentMin: null, - tickExponentMax: null, - showMinorTicks: true, - showTicks: null, - - // bullet: "\u2022" - // middle-point: "\u00B7" - // this.isAnchorTopOrBottom() ? ".." : ":" - hiddenLabelText: "\u00B7", - - _isScaleSetup: false, - - _createLogInstanceId: function(){ - return this.base() + " - " + this.axis.id; - }, - - getTicks: function(){ - return this._layoutInfo && this._layoutInfo.ticks; - }, - - _calcLayout: function(layoutInfo){ - - var scale = this.axis.scale; - - if(!this._isScaleSetup){ - this.pvScale = scale; - this.scale = scale; // TODO: At least HeatGrid depends on this. Maybe Remove? - - this.extend(scale, "scale"); // TODO - review extension interface - - this._isScaleSetup = true; - } - - if(scale.isNull){ - layoutInfo.axisSize = 0; - } else { - this._calcLayoutCore(layoutInfo); - } - - return this.createAnchoredSize(layoutInfo.axisSize, layoutInfo.clientSize); - }, - - _calcLayoutCore: function(layoutInfo){ - // Fixed axis size? - var axisSize = layoutInfo.desiredClientSize[this.anchorOrthoLength()]; - - layoutInfo.axisSize = axisSize; // may be undefined - - if (this.isDiscrete && this.useCompositeAxis){ - if(layoutInfo.axisSize == null){ - layoutInfo.axisSize = 50; - } - } else { - layoutInfo.textAngle = def.number.as(this._getExtension('label', 'textAngle'), 0); - layoutInfo.textMargin = def.number.as(this._getExtension('label', 'textMargin'), 3); - - /* I - Calculate ticks - * --> layoutInfo.{ ticks, ticksText, maxTextWidth } - */ - this._calcTicks(); - - if(this.scale.type === 'discrete'){ - this._calcDiscreteTicksHidden(); - } - - /* II - Calculate NEEDED axisSize so that all tick's labels fit */ - this._calcAxisSizeFromLabel(); // -> layoutInfo.requiredAxisSize, layoutInfo.labelBBox - - if(layoutInfo.axisSize == null){ - layoutInfo.axisSize = layoutInfo.requiredAxisSize; - } - - /* III - Calculate Trimming Length if: FIXED/NEEDED > AVAILABLE */ - this._calcMaxTextLengthThatFits(); - - - /* IV - Calculate overflow paddings */ - this._calcOverflowPaddings(); - } - }, - - _calcAxisSizeFromLabel: function(){ - this._calcLabelBBox(); - this._calcAxisSizeFromLabelBBox(); - }, - - // --> layoutInfo.labelBBox - _calcLabelBBox: function(){ - var layoutInfo = this._layoutInfo; - - var align = this._getExtension('label', 'textAlign'); - if(typeof align !== 'string'){ - align = this.isAnchorTopOrBottom() ? - "center" : - (this.anchor == "left") ? "right" : "left"; - } - - var baseline = this._getExtension('label', 'textBaseline'); - if(typeof baseline !== 'string'){ - switch (this.anchor) { - case "right": - case "left": - case "center": - baseline = "middle"; - break; - - case "bottom": - baseline = "top"; - break; - - default: - //case "top": - baseline = "bottom"; - //break; - } - } - - return (layoutInfo.labelBBox = pvc.text.getLabelBBox( - layoutInfo.maxTextWidth != null ? layoutInfo.maxTextWidth : layoutInfo._maxTextWidth, - layoutInfo.textHeight, - align, - baseline, - layoutInfo.textAngle, - layoutInfo.textMargin)); - }, - - _calcAxisSizeFromLabelBBox: function(){ - var layoutInfo = this._layoutInfo; - var labelBBox = layoutInfo.labelBBox; - - // The length not over the plot area - var length = this._getLabelBBoxQuadrantLength(labelBBox, this.anchor); - - // -------------- - - var axisSize = this.tickLength + length; - - // Add equal margin on both sides? - var angle = labelBBox.sourceAngle; - if(!(angle === 0 && this.isAnchorTopOrBottom())){ - // Text height already has some free space in that case - // so no need to add more. - axisSize += this.tickLength; - } - - layoutInfo.requiredAxisSize = axisSize; - }, - - _getLabelBBoxQuadrantLength: function(labelBBox, quadrantSide){ - // labelBBox coordinates are relative to the anchor point - // x points to the right, y points downwards - // T - // ^ - // | - // L <---0---> R - // | - // v - // B - // - // +--> xx - // | - // v yy - // - // x1 <= x2 - // y1 <= y2 - // - // p1 +-------+ - // | | - // +-------+ p2 - - var length; - switch(quadrantSide){ - case 'left': length = -labelBBox.x; break; - case 'right': length = labelBBox.x2; break; - case 'top': length = -labelBBox.y; break; - case 'bottom': length = labelBBox.y2; break; - } - - return Math.max(length, 0); - }, - - _calcOverflowPaddings: function(){ - if(!this._layoutInfo.canChange){ - if(pvc.debug >= 2){ - this._log("[WARNING] Layout cannot change. Skipping calculation of overflow paddings."); - } - return; - } - - if(!this._layoutInfo.labelBBox){ - this._calcLabelBBox(); - } - - this._calcOverflowPaddingsFromLabelBBox(); - }, - - _calcOverflowPaddingsFromLabelBBox: function(){ - var overflowPaddings = null; - - var layoutInfo = this._layoutInfo; - var ticks = layoutInfo.ticks; - var tickCount = ticks.length; - if(tickCount){ - var paddings = layoutInfo.paddings; - var labelBBox = layoutInfo.labelBBox; - var isTopOrBottom = this.isAnchorTopOrBottom(); - var begSide = isTopOrBottom ? 'left' : 'top' ; - var endSide = isTopOrBottom ? 'right' : 'bottom'; - var isDiscrete = this.scale.type === 'discrete'; - - var clientLength = layoutInfo.clientSize[this.anchorLength()]; - this.axis.setScaleRange(clientLength); - - var sideTickOffset; - if(isDiscrete){ - var halfBand = this.scale.range().step / 2; // don't use .band, cause it does not include margins... - sideTickOffset = def.set({}, - begSide, halfBand, - endSide, halfBand); - } else { - sideTickOffset = def.set({}, - begSide, this.scale(ticks[0]), - endSide, clientLength - this.scale(ticks[tickCount - 1])); - } - - [begSide, endSide].forEach(function(side){ - var overflowPadding = this._getLabelBBoxQuadrantLength(labelBBox, side); - if(overflowPadding > 0){ - // Discount real paddings that this panel already has - // cause they're, in principle, empty space that can be occupied. - overflowPadding -= (paddings[side] || 0); - if(overflowPadding > 0){ - // On discrete axes, half of the band width is not yet overflow. - overflowPadding -= sideTickOffset[side]; - if(overflowPadding > 1){ // small delta to avoid frequent relayouts... (the reported font height often causes this kind of "error" in BBox calculation) - if(isDiscrete){ - // reduction of space causes reduction of band width - // which in turn usually causes the overflowPadding to increase, - // as the size of the text usually does not change. - // Ask a little bit more to hit the target faster. - overflowPadding *= 1.05; - } - - if(!overflowPaddings){ - overflowPaddings= {}; - } - overflowPaddings[side] = overflowPadding; - } - } - } - }, this); - - if(pvc.debug >= 6 && overflowPaddings){ - this._log("OverflowPaddings = " + pvc.stringify(overflowPaddings)); - } - } - - layoutInfo.overflowPaddings = overflowPaddings; - }, - - _calcMaxTextLengthThatFits: function(){ - var layoutInfo = this._layoutInfo; - - if(this.compatVersion() <= 1){ - layoutInfo.maxTextWidth = null; - return; - } - - var availableClientLength = layoutInfo.clientSize[this.anchorOrthoLength()]; - - var efSize = Math.min(layoutInfo.axisSize, availableClientLength); - if(efSize >= (layoutInfo.requiredAxisSize - this.tickLength)){ // let overflow by at most tickLength - // Labels fit - // Clear to avoid any unnecessary trimming - layoutInfo.maxTextWidth = null; - } else { - // Text may not fit. - // Calculate maxTextWidth where text is to be trimmed. - var labelBBox = layoutInfo.labelBBox; - - // Now move backwards, to the max text width... - var maxOrthoLength = efSize - 2 * this.tickLength; - - // A point at the maximum orthogonal distance from the anchor - // Points in the outwards orthogonal direction. - var mostOrthoDistantPoint; - var parallelDirection; - switch(this.anchor){ - case 'left': - parallelDirection = pv.vector(0, 1); - mostOrthoDistantPoint = pv.vector(-maxOrthoLength, 0); - break; - - case 'right': - parallelDirection = pv.vector(0, 1); - mostOrthoDistantPoint = pv.vector(maxOrthoLength, 0); - break; - - case 'top': - parallelDirection = pv.vector(1, 0); - mostOrthoDistantPoint = pv.vector(0, -maxOrthoLength); - break; - - case 'bottom': - parallelDirection = pv.vector(1, 0); - mostOrthoDistantPoint = pv.vector(0, maxOrthoLength); - break; - } - - var orthoOutwardsDir = mostOrthoDistantPoint.norm(); - - // Intersect the line that passes through mostOrthoDistantPoint, - // and has the direction parallelDirection with - // the top side and with the bottom side of the *original* label box. - var corners = labelBBox.source.points(); - var botL = corners[0]; - var botR = corners[1]; - var topR = corners[2]; - var topL = corners[3]; - - var topLRSideDir = topR.minus(topL); - var botLRSideDir = botR.minus(botL); - var intersect = pv.SvgScene.lineIntersect; - var botI = intersect(mostOrthoDistantPoint, parallelDirection, botL, botLRSideDir); - var topI = intersect(mostOrthoDistantPoint, parallelDirection, topL, topLRSideDir); - - // botI and topI will replace two of the original BBox corners - // The original corners that are at the side of the - // the line that passes at mostOrthoDistantPoint and has direction parallelDirection (dividing line) - // further away to the axis, are to be replaced. - - var sideLRWidth = labelBBox.sourceTextWidth; - var maxTextWidth = sideLRWidth; - - var botLI = botI.minus(botL); - var botLILen = botLI.length(); - if(botLILen <= sideLRWidth && botLI.dot(topLRSideDir) >= 0){ - // botI is between botL and botR - // One of botL and botR is in one side and - // the other at the other side of the dividing line. - // On of the sides will be cut-off. - // The cut-off side is the one whose points have the biggest - // distance measured relative to orthoOutwardsDir - - if(botL.dot(orthoOutwardsDir) < botR.dot(orthoOutwardsDir)){ - // botR is farther, so is on the cut-off side - maxTextWidth = botLILen; // surely, botLILen < maxTextWidth - } else { - maxTextWidth = botI.minus(botR).length(); // idem - } - } - - var topLI = topI.minus(topL); - var topLILen = topLI.length(); - if(topLILen <= sideLRWidth && topLI.dot(topLRSideDir) >= 0){ - // topI is between topL and topR - - if(topL.dot(orthoOutwardsDir) < topR.dot(orthoOutwardsDir)){ - // topR is farther, so is on the cut-off side - maxTextWidth = Math.min(maxTextWidth, topLILen); - } else { - maxTextWidth = Math.min(maxTextWidth, topI.minus(topR).length()); - } - } - - // One other detail. - // When align (anchor) is center, - // just cutting on one side of the label original box - // won't do, because when text is centered, the cut we make in length - // ends up distributed by both sides... - if(labelBBox.sourceAlign === 'center'){ - var cutWidth = sideLRWidth - maxTextWidth; - - // Cut same width on the opposite side. - maxTextWidth -= cutWidth; - } - - layoutInfo.maxTextWidth = maxTextWidth; - - if(pvc.debug >= 3){ - this._log("Trimming labels' text at length " + maxTextWidth.toFixed(2) + "px maxOrthoLength=" + maxOrthoLength.toFixed(2) + "px"); - } - } - }, - - // ---------------- - - _calcTicks: function(){ - var layoutInfo = this._layoutInfo; - - layoutInfo.textHeight = pv.Text.fontHeight(this.font); - layoutInfo.maxTextWidth = null; - - // Reset scale to original unrounded domain - this.axis.setTicks(null); - - // update maxTextWidth, ticks and ticksText - switch(this.scale.type){ - case 'discrete': this._calcDiscreteTicks(); break; - case 'timeSeries': this._calcTimeSeriesTicks(); break; - case 'numeric': this._calcNumberTicks(layoutInfo); break; - default: throw def.error.operationInvalid("Undefined axis scale type"); - } - - this.axis.setTicks(layoutInfo.ticks); - - var clientLength = layoutInfo.clientSize[this.anchorLength()]; - this.axis.setScaleRange(clientLength); - - if(layoutInfo.maxTextWidth == null){ - layoutInfo.maxTextWidth = - def.query(layoutInfo.ticksText) - .select(function(text){ return pv.Text.measure(text, this.font).width; }, this) - .max(); - } - - // Backup value, cause the first one is cleared to prevent label trimming - // but the max text width is important for other uses - layoutInfo._maxTextWidth = layoutInfo.maxTextWidth; - }, - - _calcDiscreteTicks: function(){ - var layoutInfo = this._layoutInfo; - var role = this.chart.visualRoles(this.roleName); - var data = role.flatten(this.chart.data, {visible: true}); - - layoutInfo.data = data; - layoutInfo.ticks = data._children; - - // If the discrete data is of a single Date value type, - // we want to format the category values with an appropriate precision, - // instead of showing the default label. - var format, dimType; - var grouping = role.grouping; - if(grouping.isSingleDimension && - (dimType = grouping.firstDimensionType()) && - (dimType.valueType === Date)){ - // Calculate precision from data dimension's extent - var extent = data.dimensions(dimType.name).extent(); - // At least two atoms are required - if(extent && extent.min !== extent.max){ - var scale = new pv.Scale.linear(extent.min.value, extent.max.value); - // Force "best" tick and tick format determination - scale.ticks(); - var tickFormatter = this.axis.option('TickFormatter'); - if(tickFormatter){ - scale.tickFormatter(tickFormatter); - } - - format = function(child){ return scale.tickFormat(child.value); }; - } - } - - if(!format){ - format = function(child){ return child.absLabel; }; - } - - layoutInfo.ticksText = data._children.map(format); - }, - - - - _calcTimeSeriesTicks: function(){ - this._calcContinuousTicks(this._layoutInfo/*, this.desiredTickCount */); // not used - }, - - _calcNumberTicks: function(/*layoutInfo*/){ - var desiredTickCount = this.desiredTickCount; - if(desiredTickCount == null){ - if(this.isAnchorTopOrBottom()){ - this._calcNumberHTicks(); - return; - } - - desiredTickCount = this._calcNumberVDesiredTickCount(); - } - - this._calcContinuousTicks(this._layoutInfo, desiredTickCount); - }, - - // -------------- - - _calcContinuousTicks: function(ticksInfo, desiredTickCount){ - this._calcContinuousTicksValue(ticksInfo, desiredTickCount); - this._calcContinuousTicksText(ticksInfo); - }, - - _calcContinuousTicksValue: function(ticksInfo, desiredTickCount){ - ticksInfo.ticks = this.scale.ticks( - desiredTickCount, { - roundInside: this.domainRoundMode !== 'tick', - numberExponentMin: this.tickExponentMin, - numberExponentMax: this.tickExponentMax - }); - - if(pvc.debug > 4){ - this._log("DOMAIN: " + pvc.stringify(this.scale.domain())); - this._log("TICKS: " + pvc.stringify(ticksInfo.ticks)); - } - }, - - _calcContinuousTicksText: function(ticksInfo){ - - ticksInfo.ticksText = def.query(ticksInfo.ticks) - .select(function(tick){ return this.scale.tickFormat(tick); }, this) - .array(); - }, - - // -------------- - - _calcDiscreteTicksHidden: function(){ - return this._tickIncludeModulo = this._calcDiscreteTicksHiddenCore(); - }, - - _calcDiscreteTicksHiddenCore: function(){ - var mode = this.axis.option('OverlappedLabelsMode'); - if(mode !== 'hide'){ - return 1; - } - - var layoutInfo = this._layoutInfo; - var ticks = layoutInfo.ticks; - var tickCount = ticks.length; - if(tickCount <= 1) { - return 1; - } - - // Calculate includeModulo depending on labelSpacingMin - - // scale is already setup - - // How much label anchors are separated from each other - // (in the direction of the axis) - var b = this.scale.range().step; // don't use .band, cause it does not include margins... - - // Height of label box - var h = layoutInfo.textHeight; - - // Width of label box - var w = layoutInfo.maxTextWidth; // Should use the average value? - - if(!(w > 0 && h > 0 && b > 0)){ - return 1; - } - - // Minimum space that the user wants separating - // the closest edges of the bounding boxes of two consecutive labels, - // measured perpendicularly to the label text direction. - var sMin = h * this.labelSpacingMin /* parameter in em */; - - // The angle that the text makes to the x axis (clockwise,y points downwards) - var a = layoutInfo.textAngle; - - var isTopOrBottom = this.isAnchorTopOrBottom(); - var sinOrCos = isTopOrBottom ? 'sin' : 'cos'; - var cosOrSin = !isTopOrBottom ? 'sin' : 'cos'; - - var tickIncludeModulo = 1; - do{ - // Effective distance between anchors, - // that results from showing only - // one in every 'tickIncludeModulo' ticks. - var bEf = tickIncludeModulo * b; - - // The space that separates the closest edges, - // that are parallel to the text direction, - // of the bounding boxes of - // two consecutive (not skipped) labels. - var sBase = bEf * Math.abs(Math[sinOrCos](a)) - h; - - // The same, for the edges orthogonal to the text direction - var sOrtho = bEf * Math.abs(Math[cosOrSin](a)) - w; - - // At least one of this distances must respect sMin - if(sBase >= sMin || sOrtho >= sMin){ - break; - } - - // Hide one more tick - tickIncludeModulo++; - - // Are there still at least two ticks left? - } while(Math.ceil(tickCount / tickIncludeModulo) > 1); - - if(tickIncludeModulo > 1 && pvc.debug >= 3){ - this._log("Showing only one in every " + tickIncludeModulo + " tick labels"); - } - - return tickIncludeModulo; - }, - - // -------------- - - _calcNumberVDesiredTickCount: function(){ - var layoutInfo = this._layoutInfo; - var lineHeight = layoutInfo.textHeight * (1 + Math.max(0, this.labelSpacingMin /*em*/)); - var clientLength = layoutInfo.clientSize[this.anchorLength()]; - - return Math.max(1, ~~(clientLength / lineHeight)); - }, - - _calcNumberHTicks: function(){ - var layoutInfo = this._layoutInfo; - var clientLength = layoutInfo.clientSize[this.anchorLength()]; - var spacing = layoutInfo.textHeight * Math.max(0, this.labelSpacingMin/*em*/); - var desiredTickCount = this._calcNumberHDesiredTickCount(spacing); - - var doLog = (pvc.debug >= 7); - var dir, prevResultTickCount; - var ticksInfo, lastBelow, lastAbove; - do { - if(doLog){ this._log("calculateNumberHTicks TickCount IN desired = " + desiredTickCount); } - - ticksInfo = {}; - - this._calcContinuousTicksValue(ticksInfo, desiredTickCount); - - var ticks = ticksInfo.ticks; - - var resultTickCount = ticks.length; - - if(ticks.exponentOverflow){ - // TODO: Check if this part of the algorithm is working ok - - // Cannot go anymore in the current direction, if any - if(dir == null){ - if(ticks.exponent === this.exponentMin){ - lastBelow = ticksInfo; - dir = 1; - } else { - lastAbove = ticksInfo; - dir = -1; - } - } else if(dir === 1){ - if(lastBelow){ - ticksInfo = lastBelow; - } - break; - } else { // dir === -1 - if(lastAbove){ - ticksInfo = lastAbove; - } - break; - } - - } else if(prevResultTickCount == null || resultTickCount !== prevResultTickCount){ - - if(doLog){ - this._log("calculateNumberHTicks TickCount desired/resulting = " + desiredTickCount + " -> " + resultTickCount); - } - - prevResultTickCount = resultTickCount; - - this._calcContinuousTicksText(ticksInfo); - - var length = this._calcNumberHLength(ticksInfo, spacing); - var excessLength = ticksInfo.excessLength = length - clientLength; - var pctError = ticksInfo.error = Math.abs(excessLength / clientLength); - - if(doLog){ - this._log("calculateNumberHTicks error=" + (excessLength >= 0 ? "+" : "-") + (ticksInfo.error * 100).toFixed(0) + "% count=" + resultTickCount + " step=" + ticks.step); - this._log("calculateNumberHTicks Length client/resulting = " + clientLength + " / " + length + " spacing = " + spacing); - } - - if(excessLength > 0){ - // More ticks than can fit - if(desiredTickCount === 1){ - // Edge case - // Cannot make dir = -1 ... - if(resultTickCount === 3 && pctError <= 1){ - // remove the middle tick - ticksInfo.ticks.splice(1,1); - ticksInfo.ticksText.splice(1,1); - ticksInfo.ticks.step *= 2; - } else { - // keep only the first tick - ticksInfo.ticks.length = 1; - ticksInfo.ticksText.length = 1; - } - delete ticksInfo.maxTextWidth; - break; - } - - if(lastBelow){ - // We were below max length and then overshot... - // Choose the best conforming one - // Always choose the one that conforms to MinSpacing - //if(pctError > lastBelow.error){ - ticksInfo = lastBelow; - //} - break; - } - - // Backup last *above* calculation - lastAbove = ticksInfo; - - dir = -1; - } else { - // Less ticks than could fit - - if(pctError <= 0.05 || dir === -1){ - // Acceptable - // or - // Already had exceeded the length and had decided to go down -// if(lastAbove && pctError > lastAbove.error){ -// ticksInfo = lastAbove; -// } - - break; - } - - // Backup last *below* calculation - lastBelow = ticksInfo; - - dir = +1; - } - } - - desiredTickCount += dir; - } while(true); - - if(ticksInfo){ - layoutInfo.ticks = ticksInfo.ticks; - layoutInfo.ticksText = ticksInfo.ticksText; - layoutInfo.maxTextWidth = ticksInfo.maxTextWidth; - - if(pvc.debug >= 5){ - this._log("calculateNumberHTicks RESULT error=" + (ticksInfo.excessLength >= 0 ? "+" : "-") + (ticksInfo.error * 100).toFixed(0) + "% count=" + ticksInfo.ticks.length + " step=" + ticksInfo.ticks.step); - } - } - - if(doLog){ this._log("calculateNumberHTicks END"); } - }, - - _calcNumberHDesiredTickCount: function(spacing){ - // The initial tick count is determined - // from the formatted min and max values of the domain. - var layoutInfo = this._layoutInfo; - var domainTextLength = this.scale.domain().map(function(tick){ - tick = +tick.toFixed(2); // crop some decimal places... - var text = this.scale.tickFormat(tick); - return pv.Text.measure(text, this.font).width; - }, this); - - var avgTextLength = Math.max((domainTextLength[1] + domainTextLength[0]) / 2, layoutInfo.textHeight); - - var clientLength = layoutInfo.clientSize[this.anchorLength()]; - - return Math.max(1, ~~(clientLength / (avgTextLength + spacing))); - }, - - _calcNumberHLength: function(ticksInfo, spacing){ - // Measure full width, with spacing - var ticksText = ticksInfo.ticksText; - var maxTextWidth = - def.query(ticksText) - .select(function(text){ - return pv.Text.measure(text, this.font).width; - }, this) - .max(); - - /* - * Include only half the text width on edge labels, - * cause centered labels are the most common scenario. - * - * |w s ww s ww s w| - * - */ - return Math.max(maxTextWidth, (ticksText.length - 1) * (maxTextWidth + spacing)); - }, - - _createCore: function() { - if(this.scale.isNull){ - return; - } - - // Range - var clientSize = this._layoutInfo.clientSize; - var paddings = this._layoutInfo.paddings; - - var begin_a = this.anchorOrtho(); - var end_a = this.anchorOpposite(begin_a); - var size_a = this.anchorOrthoLength(begin_a); - - var rMin = this.ruleCrossesMargin ? -paddings[begin_a] : 0; - var rMax = clientSize[size_a] + (this.ruleCrossesMargin ? paddings[end_a] : 0); - var rSize = rMax - rMin; - - var ruleParentPanel = this.pvPanel; - - this._rSize = rSize; - - var rootScene = this._getRootScene(); - - this.pvRule = new pvc.visual.Rule(this, this.pvPanel, { - extensionId: 'rule' - }) - .lock('data', [rootScene]) - .override('defaultColor', def.fun.constant("#666666")) - // ex: anchor = bottom - .lock(this.anchorOpposite(), 0) // top (of the axis panel) - .lock(begin_a, rMin ) // left - .lock(size_a, rSize) // width - .pvMark - .zOrder(30) - .strokeDasharray(null) // don't inherit from parent panel - .lineCap('square') // So that begin/end ticks better join with the rule - ; - - if (this.isDiscrete){ - if(this.useCompositeAxis){ - this.renderCompositeOrdinalAxis(); - } else { - this.renderOrdinalAxis(); - } - } else { - this.renderLinearAxis(); - } - }, - - _getExtensionId: function(){ - return ''; // NOTE: this is different from specifying null - }, - - _getRootScene: function(){ - if(!this._rootScene){ - var rootScene = - this._rootScene = - new pvc.visual.CartesianAxisRootScene(null, { - panel: this, - group: this._getRootData() - }); - - var layoutInfo = this._layoutInfo; - var ticksText = layoutInfo.ticksText; - if (this.isDiscrete){ - if(this.useCompositeAxis){ - this._buildCompositeScene(rootScene); - } else { - layoutInfo.ticks.forEach(function(tickData, index){ - new pvc.visual.CartesianAxisTickScene(rootScene, { - group: tickData, - tick: tickData.value, - tickRaw: tickData.rawValue, - tickLabel: ticksText[index] - }); - }); - } - } else { - layoutInfo.ticks.forEach(function(majorTick, index){ - new pvc.visual.CartesianAxisTickScene(rootScene, { - tick: majorTick, - tickRaw: majorTick, - tickLabel: ticksText[index] - }); - }, this); - } - } - - return this._rootScene; - }, - - _buildCompositeScene: function(rootScene){ - - var isV1Compat = this.compatVersion() <= 1; - - // Need this for code below not to throw when drawing the root - rootScene.vars.tick = new pvc.visual.ValueLabelVar('', ""); - - recursive(rootScene); - - function recursive(scene){ - var data = scene.group; - if(isV1Compat){ - // depending on the specific version the - // properties nodeLabel and label existed as well - var tickVar = scene.vars.tick; - scene.nodeValue = scene.value = tickVar.rawValue; - scene.nodeLabel = scene.label = tickVar.label; - } - - if(data.childCount()){ - data - .children() - .each(function(childData){ - var childScene = new pvc.visual.CartesianAxisTickScene(scene, { - group: childData, - tick: childData.value, - tickRaw: childData.rawValue, - tickLabel: childData.label - }); - - recursive(childScene); - }); - } - } - }, - - _getRootData: function(){ - var chart = this.chart; - var data = chart.data; - - if (this.isDiscrete && this.useCompositeAxis){ - var orientation = this.anchor; - var reverse = orientation == 'bottom' || orientation == 'left'; - data = chart.visualRoles(this.roleName) - .select(data, {visible: true, reverse: reverse}); - } - - return data; - }, - - _getOrthoScale: function(){ - var orthoType = this.axis.type === 'base' ? 'ortho' : 'base'; - return this.chart.axes[orthoType].scale; // index 0 - }, - - _getOrthoAxis: function(){ - var orthoType = this.axis.type === 'base' ? 'ortho' : 'base'; - return this.chart.axes[orthoType]; // index 0 - }, - - renderOrdinalAxis: function(){ - var myself = this, - scale = this.scale, - hiddenLabelText = this.hiddenLabelText, - anchorOpposite = this.anchorOpposite(), - anchorLength = this.anchorLength(), - anchorOrtho = this.anchorOrtho(), - anchorOrthoLength = this.anchorOrthoLength(), - layoutInfo = this._layoutInfo, - pvRule = this.pvRule, - ticks = layoutInfo.ticks, - data = layoutInfo.data, - itemCount = layoutInfo.ticks.length, - rootScene = this._getRootScene(), - includeModulo = this._tickIncludeModulo, - isV1Compat = this.compatVersion() <= 1; - - rootScene.vars.tickIncludeModulo = includeModulo; - rootScene.vars.hiddenLabelText = hiddenLabelText; - - var wrapper; - if(isV1Compat){ - // For use in child marks of pvTicksPanel - var DataElement = function(tickVar){ - this.value = - this.absValue = tickVar.rawValue; - this.nodeName = '' + (this.value || ''); - this.path = this.nodeName ? [this.nodeName] : []; - this.label = - this.absLabel = tickVar.label; - }; - - DataElement.prototype.toString = function(){ - return ''+this.value; - }; - - wrapper = function(v1f){ - return function(tickScene){ - // Fix index due to the introduction of - // pvTicksPanel panel. - var markWrapped = Object.create(this); - markWrapped.index = this.parent.index; - - return v1f.call(markWrapped, new DataElement(tickScene.vars.tick)); - }; - }; - } - - // Ticks correspond to each data in datas. - // Ticks are drawn at the center of each band. - - var pvTicksPanel = new pvc.visual.Panel(this, this.pvPanel, { - extensionId: 'ticksPanel' - }) - .lock('data', rootScene.childNodes) - // This non-extendable property stores - // if the tick would be hidden by - // virtue of the includeModulo effect. - .localProperty('hidden') - .lockMark('hidden', function(){ // for use by - return (this.index % includeModulo) !== 0; - }) - .lock(anchorOpposite, 0) // top (of the axis panel) - .lockMark(anchorOrtho, function(tickScene){ - return scale(tickScene.vars.tick.value); - }) - .lock('strokeDasharray', null) - .lock('strokeStyle', null) - .lock('fillStyle', null) - .lock('lineWidth', 0) - .pvMark - .zOrder(20) // below axis rule - ; - - if(isV1Compat || this.showTicks){ - var pvTicks = this.pvTicks = new pvc.visual.Rule(this, pvTicksPanel, { - extensionId: 'ticks', - wrapper: wrapper - }) - .lock('data') // Inherited - .intercept('visible', function(){ - return !this.pvMark.parent.hidden() && - this.delegateExtension(true); - }) - .optional('lineWidth', 1) - .lock(anchorOpposite, 0) // top - .lock(anchorOrtho, 0) // left - .lock(anchorLength, null) - .optional(anchorOrthoLength, this.tickLength * 2/3) // slightly smaller than continuous ticks - .override('defaultColor', function(type){ - if(isV1Compat) { - return pv.Color.names.transparent; - } - - // Inherit ticks color from rule - // Control visibility through .visible or lineWidth - return pvRule.scene ? - pvRule.scene[0].strokeStyle : - "#666666"; - }) - .pvMark - ; - } - - // Determine anchored text properties - var baseline; - var align; - switch(this.anchor){ - case 'top': - align = 'center'; - baseline = 'bottom'; - break; - - case 'bottom': - align = 'center'; - baseline = 'top'; - break; - - case 'left': - align = 'right'; - baseline = 'middle'; - break; - - case 'right': - align = 'left'; - baseline = 'middle'; - break; - } - - var font = this.font; - - var maxTextWidth = this._layoutInfo.maxTextWidth; - if(!isFinite(maxTextWidth)){ - maxTextWidth = 0; - } - - // An pv anchor on pvTick is not used, on purpose, - // cause if it were, hidding the tick with .visible, - // would mess the positioning of the label... - this.pvLabel = new pvc.visual.Label( - this, - pvTicksPanel, - { - extensionId: 'label', - noClick: false, - noDoubleClick: false, - noSelect: false, - noTooltip: false, - noHover: false, // TODO: to work, scenes would need a common root - wrapper: wrapper, - tooltipArgs: { - // TODO: should be an option whether a data tooltip is desired - buildTooltip: function(context){ return context.scene.vars.tick.label; }, - isLazy: false, - - options: { - gravity: this._calcTipsyGravity() - } - } - }) - .intercept('visible', function(tickScene){ - return !this.pvMark.parent.hidden() ? - this.delegateExtension(true) : - !!tickScene.vars.hiddenLabelText; - }) - .intercept('text', function(tickScene){ - var text; - if(this.pvMark.parent.hidden()){ - text = tickScene.vars.hiddenLabelText; - } else { - // Allow late overriding (does not affect layout..) - text = this.delegateExtension(); - if(text === undefined){ - text = tickScene.vars.tick.label; - } - if(maxTextWidth){ - text = pvc.text.trimToWidthB(maxTextWidth, text, font, "..", false); - } - } - - return text; - }) - .pvMark - .zOrder(40) // above axis rule - - .lock(anchorOpposite, this.tickLength) - .lock(anchorOrtho, 0) - - .font(font) - .textStyle("#666666") - .textAlign(align) - .textBaseline(baseline) - ; - - this._debugTicksPanel(pvTicksPanel); - }, - - _debugTicksPanel: function(pvTicksPanel){ - if(pvc.debug >= 16){ // one more than general debug box model - var corners = this._layoutInfo.labelBBox.source.points(); - - // Close the path - if(corners.length > 1){ - // not changing corners on purpose - corners = corners.concat(corners[0]); - } - - pvTicksPanel - // Single-point panel (w=h=0) - .add(pv.Panel) - [this.anchorOpposite()](this.tickLength) - [this.anchorOrtho()](0) - [this.anchorLength()](0) - [this.anchorOrthoLength()](0) - .fillStyle(null) - .strokeStyle(null) - .lineWidth(0) - .add(pv.Line) - .visible(function(){ - var gp = this.parent.parent; - return !gp.hidden || !gp.hidden(); - }) - .data(corners) - .left(function(p){ return p.x; }) - .top (function(p){ return p.y; }) - .strokeStyle('red') - .lineWidth(0.5) - .strokeDasharray('-') - ; - } - }, - - renderLinearAxis: function(){ - // NOTE: Includes time series, - // so "tickScene.vars.tick.value" may be a number or a Date object... - - var scale = this.scale, - orthoAxis = this._getOrthoAxis(), - orthoScale = orthoAxis.scale, - pvRule = this.pvRule, - anchorOpposite = this.anchorOpposite(), - anchorLength = this.anchorLength(), - anchorOrtho = this.anchorOrtho(), - anchorOrthoLength = this.anchorOrthoLength(), - rootScene = this._getRootScene(); - - var wrapper; - if(this.compatVersion() <= 1){ - wrapper = function(v1f){ - return function(tickScene){ - // Fix index due to the introduction of - // pvTicksPanel panel. - var markWrapped = Object.create(this); - markWrapped.index = this.parent.index; - - return v1f.call(markWrapped, tickScene.vars.tick.rawValue); - }; - }; - } - - var pvTicksPanel = new pvc.visual.Panel(this, this.pvPanel, { - extensionId: 'ticksPanel' - }) - .lock('data', rootScene.childNodes) - .lock(anchorOpposite, 0) // top (of the axis panel) - .lockMark(anchorOrtho, function(tickScene){ - return scale(tickScene.vars.tick.value); - }) - .lock('strokeStyle', null) - .lock('fillStyle', null) - .lock('lineWidth', 0) - .pvMark - .zOrder(20) // below axis rule - ; - - if(this.showTicks){ - // (MAJOR) ticks - var pvTicks = this.pvTicks = new pvc.visual.Rule(this, pvTicksPanel, { - extensionId: 'ticks', - wrapper: wrapper - }) - .lock('data') // Inherited - .override('defaultColor', function(){ - // Inherit axis color - // Control visibility through color or through .visible - // NOTE: the rule only has one scene/instance - return pvRule.scene ? - pvRule.scene[0].strokeStyle : - "#666666"; - }) - .lock(anchorOpposite, 0) // top - .lock(anchorOrtho, 0) // left - .lock(anchorLength, null) - .optional(anchorOrthoLength, this.tickLength) - .pvMark - ; - - // MINOR ticks are between major scale ticks - if(this.showMinorTicks){ - var layoutInfo = this._layoutInfo; - var ticks = layoutInfo.ticks; - var tickCount = ticks.length; - // Assume a linear scale - var minorTickOffset = tickCount > 1 ? - Math.abs(scale(ticks[1]) - scale(ticks[0])) / 2 : - 0; - - this.pvMinorTicks = new pvc.visual.Rule(this, this.pvTicks, { - extensionId: 'minorTicks', - wrapper: wrapper - }) - .lock('data') // Inherited - .intercept('visible', function(){ - // The last minor tick isn't visible - only show between major ticks. - // Hide if the previous major tick is hidden. - var visible = (this.index < tickCount - 1) && - (!pvTicks.scene || pvTicks.scene[0].visible); - - return visible && this.delegateExtension(true); - }) - .override('defaultColor', function(){ - // Inherit ticks color - // Control visibility through color or through .visible - return pvTicks.scene ? - pvTicks.scene[0].strokeStyle : - pv.Color.names.d; - }) - .lock(anchorOpposite, 0) // top - .lock(anchorLength, null) - .optional(anchorOrthoLength, this.tickLength / 2) - .lockMark(anchorOrtho, minorTickOffset) - .pvMark - ; - } - } - - this.renderLinearAxisLabel(pvTicksPanel, wrapper); - - this._debugTicksPanel(pvTicksPanel); - }, - - renderLinearAxisLabel: function(pvTicksPanel, wrapper){ - // Labels are visible (only) on MAJOR ticks, - // On first and last tick care is taken - // with their H/V alignment so that - // the label is not drawn off the chart. - - // Use this margin instead of textMargin, - // which affects all margins (left, right, top and bottom). - // Exception is the small 0.5 textMargin set below... - var pvTicks = this.pvTicks; - var anchorOpposite = this.anchorOpposite(); - var anchorOrtho = this.anchorOrtho(); - -// var pvLabelAnchor = pvTicks -// .anchor(this.anchor) -// .addMargin(this.anchorOpposite(), 2); - - var scale = this.scale; - var font = this.font; - //@author Alterado por Edmar Moretti para a SAGE - posFixoY = ""; - if(this.chart.options.posFixoY){ - posFixoY = this.chart.options.posFixoY; - } - // - var maxTextWidth = this._layoutInfo.maxTextWidth; - if(!isFinite(maxTextWidth)){ - maxTextWidth = 0; - } - var label = this.pvLabel = new pvc.visual.Label(this, pvTicksPanel, { - extensionId: 'label', - wrapper: wrapper - }) - .lock('data') // inherited - .pvMark - - .lock(anchorOpposite, this.tickLength) - .lock(anchorOrtho, 0) - .zOrder(40) // above axis rule - .text(function(tickScene){ - //@author Alterado por Edmar Moretti para a SAGE - var text = tickScene.vars.tick.label+posFixoY; - if(maxTextWidth){ - text = pvc.text.trimToWidthB(maxTextWidth, text, font, '..', false); - } - return text; - }) - .font(this.font) - .textStyle("#666666") - //.textMargin(0.5) // Just enough for some labels not to be cut (vertical) - ; - // Label alignment - var rootPanel = this.pvPanel.root; - if(this.isAnchorTopOrBottom()){ - label - .textBaseline(anchorOpposite) - .textAlign(function(tickScene){ - var absLeft; - if(this.index === 0){ - absLeft = label.toScreenTransform().transformHPosition(label.left()); - if(absLeft <= 0){ - return 'left'; // the "left" of the text is anchored to the tick's anchor - } - } else if(this.index === tickScene.parent.childNodes.length - 1) { - absLeft = label.toScreenTransform().transformHPosition(label.left()); - if(absLeft >= rootPanel.width()){ - return 'right'; // the "right" of the text is anchored to the tick's anchor - } - } - - return 'center'; - }); - } else { - label - .textAlign(anchorOpposite) - .textBaseline(function(tickScene){ - var absTop; - if(this.index === 0){ - absTop = label.toScreenTransform().transformVPosition(label.top()); - if(absTop >= rootPanel.height()){ - return 'bottom'; // the "bottom" of the text is anchored to the tick's anchor - } - } else if(this.index === tickScene.parent.childNodes.length - 1) { - absTop = label.toScreenTransform().transformVPosition(label.top()); - if(absTop <= 0){ - return 'top'; // the "top" of the text is anchored to the tick's anchor - } - } - - return 'middle'; - }); - } - }, - - // ---------------------------- - // Click / Double-click - _onV1Click: function(context, handler){ - if(this.isDiscrete && this.useCompositeAxis){ - handler.call(context.pvMark, context.scene, context.event); - } - }, - - _onV1DoubleClick: function(context, handler){ - if(this.isDiscrete && this.useCompositeAxis){ - handler.call(context.pvMark, context.scene, context.event); - } - }, - - /** @override */ - _getSelectableMarks: function(){ - if(this.isDiscrete && this.isVisible && this.pvLabel){ - return [this.pvLabel]; - } - }, - - ///////////////////////////////////////////////// - //begin: composite axis - renderCompositeOrdinalAxis: function(){ - var myself = this, - isTopOrBottom = this.isAnchorTopOrBottom(), - axisDirection = isTopOrBottom ? 'h' : 'v', - diagDepthCutoff = 2, // depth in [-1/(n+1), 1] - vertDepthCutoff = 2, - font = this.font; - - var diagMargin = pv.Text.fontHeight(font) / 2; - - var layout = this._pvLayout = this.getLayoutSingleCluster(); - - // See what will fit so we get consistent rotation - layout.node - .def("fitInfo", null) - .height(function(tickScene, e, f){ - // Just iterate and get cutoff - var fitInfo = pvc.text.getFitInfo(tickScene.dx, tickScene.dy, tickScene.vars.tick.label, font, diagMargin); - if(!fitInfo.h){ - if(axisDirection === 'v' && fitInfo.v){ // prefer vertical - vertDepthCutoff = Math.min(diagDepthCutoff, tickScene.depth); - } else { - diagDepthCutoff = Math.min(diagDepthCutoff, tickScene.depth); - } - } - - this.fitInfo(fitInfo); - - return tickScene.dy; - }); - - // label space (left transparent) - // var lblBar = - layout.node.add(pv.Bar) - .fillStyle('rgba(127,127,127,.001)') - .strokeStyle(function(tickScene){ - if(tickScene.maxDepth === 1 || !tickScene.maxDepth) { // 0, 0.5, 1 - return null; - } - - return "rgba(127,127,127,0.3)"; //non-terminal items, so grouping is visible - }) - .lineWidth( function(tickScene){ - if(tickScene.maxDepth === 1 || !tickScene.maxDepth) { - return 0; - } - return 0.5; //non-terminal items, so grouping is visible - }) - .text(function(tickScene){ - return tickScene.vars.tick.label; - }); - - //cutoffs -> snap to vertical/horizontal - var H_CUTOFF_ANG = 0.30, - V_CUTOFF_ANG = 1.27; - - var align = isTopOrBottom ? - "center" : - (this.anchor == "left") ? "right" : "left"; - - var wrapper; - if(this.compatVersion() <= 1){ - wrapper = function(v1f){ - return function(tickScene){ - return v1f.call(this, tickScene); - }; - }; - } - - // draw labels and make them fit - this.pvLabel = new pvc.visual.Label(this, layout.label, { - extensionId: 'label', - noClick: false, - noDoubleClick: false, - noSelect: false, - noTooltip: false, - noHover: false, // TODO: to work, scenes would need a common root - wrapper: wrapper, - tooltipArgs: { - // TODO: should be an option whether a data tooltip is desired - isLazy: false, - buildTooltip: function(context){ return context.scene.vars.tick.label; }, - - options: { - gravity: this._calcTipsyGravity(), - offset: diagMargin * 2 - } - } - }) - .pvMark - .def('lblDirection','h') - .textAngle(function(tickScene){ - if(tickScene.depth >= vertDepthCutoff && tickScene.depth < diagDepthCutoff){ - this.lblDirection('v'); - return -Math.PI/2; - } - - if(tickScene.depth >= diagDepthCutoff){ - var tan = tickScene.dy/tickScene.dx; - var angle = Math.atan(tan); - //var hip = Math.sqrt(tickScene.dy*tickScene.dy + tickScene.dx*tickScene.dx); - - if(angle > V_CUTOFF_ANG){ - this.lblDirection('v'); - return -Math.PI/2; - } - - if(angle > H_CUTOFF_ANG) { - this.lblDirection('d'); - return -angle; - } - } - - this.lblDirection('h'); - return 0;//horizontal - }) - .textMargin(1) - //override central alignment for horizontal text in vertical axis - .textAlign(function(tickScene){ - return (axisDirection != 'v' || tickScene.depth >= vertDepthCutoff || tickScene.depth >= diagDepthCutoff)? 'center' : align; - }) - .left(function(tickScene) { - return (axisDirection != 'v' || tickScene.depth >= vertDepthCutoff || tickScene.depth >= diagDepthCutoff)? - tickScene.x + tickScene.dx/2 : - ((align == 'right')? tickScene.x + tickScene.dx : tickScene.x); - }) - .font(font) - .textStyle("#666666") - .text(function(tickScene){ - var fitInfo = this.fitInfo(); - var label = tickScene.vars.tick.label; - switch(this.lblDirection()){ - case 'h': - if(!fitInfo.h){//TODO: fallback option for no svg - return pvc.text.trimToWidth(tickScene.dx, label, font, '..'); - } - break; - case 'v': - if(!fitInfo.v){ - return pvc.text.trimToWidth(tickScene.dy, label, font, '..'); - } - break; - case 'd': - if(!fitInfo.d){ - //var ang = Math.atan(tickScene.dy/tickScene.dx); - var diagonalLength = Math.sqrt(tickScene.dy*tickScene.dy + tickScene.dx*tickScene.dx) ; - return pvc.text.trimToWidth(diagonalLength - diagMargin, label, font,'..'); - } - break; - } - - return label; - }) - ; - }, - - getLayoutSingleCluster: function(){ - var rootScene = this._getRootScene(), - orientation = this.anchor, - maxDepth = rootScene.group.treeHeight, - depthLength = this._layoutInfo.axisSize; - - // displace to take out bogus-root - maxDepth++; - - var baseDisplacement = depthLength / maxDepth, - margin = maxDepth > 2 ? ((1/12) * depthLength) : 0; // heuristic compensation - - baseDisplacement -= margin; - - var scaleFactor = maxDepth / (maxDepth - 1), - orthoLength = pvc.BasePanel.orthogonalLength[orientation]; - - var displacement = (orthoLength == 'width') ? - (orientation === 'left' ? [-baseDisplacement, 0] : [baseDisplacement, 0]) : - (orientation === 'top' ? [0, -baseDisplacement] : [0, baseDisplacement]); - - this.pvRule - .sign - .override('defaultColor', def.fun.constant(null)) - .override('defaultStrokeWidth', def.fun.constant(0) ) - ; - - var panel = this.pvRule - .add(pv.Panel) - [orthoLength](depthLength) - .strokeStyle(null) - .lineWidth(0) //cropping panel - .add(pv.Panel) - [orthoLength](depthLength * scaleFactor) - .strokeStyle(null) - .lineWidth(0);// panel resized and shifted to make bogus root disappear - - panel.transform(pv.Transform.identity.translate(displacement[0], displacement[1])); - - // Create with bogus-root - // pv.Hierarchy must always have exactly one root and - // at least one element besides the root - return panel.add(pv.Layout.Cluster.Fill) - .nodes(rootScene.nodes()) - .orient(orientation); - }, - - _calcTipsyGravity: function(){ - switch(this.anchor){ - case 'bottom': return 's'; - case 'top': return 'n'; - case 'left': return 'w'; - case 'right': return 'e'; - } - return 's'; - } - // end: composite axis - ///////////////////////////////////////////////// -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcAxisTitlePanel.js b/pacotes/ccc2/pvc/pvcAxisTitlePanel.js deleted file mode 100755 index 191321f..0000000 --- a/pacotes/ccc2/pvc/pvcAxisTitlePanel.js +++ /dev/null @@ -1,35 +0,0 @@ - -def -.type('pvc.AxisTitlePanel', pvc.TitlePanelAbstract) -.init(function(chart, parent, axis, options) { - - this.axis = axis; - - this.base(chart, parent, options); - - this._extensionPrefix = - axis - .extensionPrefixes - .map(function(prefix){ - return prefix + 'Title'; - }); -}) -.add({ - _calcLayout: function(layoutInfo){ - var scale = this.axis.scale; - if(!scale || scale.isNull){ - return new pvc.Size(0, 0); - } - - return this.base(layoutInfo); - }, - - _createCore: function(layoutInfo){ - var scale = this.axis.scale; - if(!scale || scale.isNull){ - return; - } - - return this.base(layoutInfo); - } -}); diff --git a/pacotes/ccc2/pvc/pvcBarAbstract.js b/pacotes/ccc2/pvc/pvcBarAbstract.js deleted file mode 100755 index 0181485..0000000 --- a/pacotes/ccc2/pvc/pvcBarAbstract.js +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * BarAbstract is the base class for generating charts of the bar family. - */ -def -.type('pvc.BarAbstract', pvc.CategoricalAbstract) -.init(function(options){ - - this.base(options); - - var parent = this.parent; - if(parent) { - this._valueRole = parent._valueRole; - } -}) -.add({ - // NOTE - // Timeseries category with bar charts are supported differently in V2 than in V1 - // They worked in v1 if the data set brought all - // categories, according to chosen timeseries scale date unit - // Then, bars were drawn with a category scale, - // whose positions ended up coinciding with the ticks in a linear axis... - // To mimic v1 behavior the category dimensions are "coerced" to isDiscrete - // The axis will be categoric, the parsing will work, - // and the formatting will be the desired one - - /** - * Initializes each chart's specific roles. - * @override - */ - _initVisualRoles: function(){ - - this.base(); - - this._addVisualRole('value', { - isMeasure: true, - isRequired: true, - isPercent: this.options.stacked, - requireSingleDimension: true, - requireIsDiscrete: false, - valueType: Number, - defaultDimension: 'value' - }); - - this._valueRole = this.visualRoles('value'); - }, - - _getCategoryRoleSpec: function(){ - var catRoleSpec = this.base(); - - // Force dimension to be discrete! - catRoleSpec.requireIsDiscrete = true; - - return catRoleSpec; - }, - - _initData: function(){ - this.base.apply(this, arguments); - - var data = this.data; - - // Cached - this._valueDim = data.dimensions(this._valueRole.firstDimensionName()); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcBarAbstractPanel.js b/pacotes/ccc2/pvc/pvcBarAbstractPanel.js deleted file mode 100755 index 20349de..0000000 --- a/pacotes/ccc2/pvc/pvcBarAbstractPanel.js +++ /dev/null @@ -1,376 +0,0 @@ - -/** - * Bar Abstract Panel. - * The base panel class for bar charts. - * - * Specific options are: - * orientation - horizontal or vertical. Default: vertical - * valuesVisible - Show or hide bar value. Default: false - * barSizeRatio - In multiple series, percentage of inner - * band occupied by bars. Default: 0.9 (90%) - * barSizeMax - Maximum size (width) of a bar in pixels. Default: 2000 - * - * Has the following protovis extension points: - * chart_ - for the main chart Panel - * bar_ - for the actual bar - * barPanel_ - for the panel where the bars sit - * barLabel_ - for the main bar label - */ -def -.type('pvc.BarAbstractPanel', pvc.CategoricalAbstractPanel) -.add({ - - pvBar: null, - pvBarLabel: null, - pvCategoryPanel: null, - pvSecondLine: null, - pvSecondDot: null, - - _creating: function(){ - // Register BULLET legend prototype marks - var groupScene = this.defaultVisibleBulletGroupScene(); - if(groupScene && !groupScene.hasRenderer()){ - var colorAxis = groupScene.colorAxis; - var drawLine = colorAxis.option('LegendDrawLine'); - var drawMarker = !drawLine || colorAxis.option('LegendDrawMarker'); - if(drawMarker){ - var keyArgs = { - drawMarker: true, - markerShape: colorAxis.option('LegendShape'), - drawRule: drawLine, - markerPvProto: new pv.Mark() - }; - - this.extend(keyArgs.markerPvProto, '', {constOnly: true}); // '' => bar itself - - groupScene.renderer( - new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs)); - } - } - }, - - /** - * @override - */ - _createCore: function(){ - this.base(); - var me = this, - chart = me.chart, - plot = me.plot, - isStacked = !!me.stacked, - isVertical = me.isOrientationVertical(), - data = me.visibleData(), // shared "categ then series" grouped data - seriesData = me.visualRoles.series.flatten(data), - rootScene = me._buildScene(data, seriesData), - orthoAxis = me.axes.ortho, - baseAxis = me.axes.base, - orthoScale = orthoAxis.scale, - orthoZero = orthoScale(0), - sceneOrthoScale = orthoAxis.sceneScale({sceneVarName: 'value', nullToZero: false}), - sceneBaseScale = baseAxis .sceneScale({sceneVarName: 'category'}), - barSizeRatio = plot.option('BarSizeRatio'), - barSizeMax = plot.option('BarSizeMax'), - barStackedMargin = plot.option('BarStackedMargin'), - baseRange = baseAxis.scale.range(), - bandWidth = baseRange.band, - barStepWidth = baseRange.step, - barWidth, - reverseSeries = isVertical === isStacked // (V && S) || (!V && !S) - ; - - if(isStacked){ - barWidth = bandWidth; - } else { - var S = seriesData.childCount(); - barWidth = S > 0 ? (bandWidth * barSizeRatio / S) : 0; - } - - if (barWidth > barSizeMax) { - barWidth = barSizeMax; - } - - me.barWidth = barWidth; - me.barStepWidth = barStepWidth; - - var wrapper; // bar and label wrapper - if(me.compatVersion() <= 1){ - /* - * V1 Data - * ---------- - * Stacked: dataSet = Series x Categ values [[]...] (type == undef -> 0) - * - * !Stacked: Categ -> Series - * Panel dataSet = VisibleCategoriesIndexes array - * Bar, Label --> padZeros( getVisibleValuesForCategIndex( . ) ) - * - * var visibleSerIndex = this.stacked ? mark.parent.index : index, - * visibleCatIndex = this.stacked ? index : mark.parent.index; - */ - wrapper = function(v1f){ - return function(scene){ - var markParent = Object.create(this.parent); - var mark = Object.create(this); - mark.parent = markParent; - - var serIndex = scene.parent.childIndex(); - var catIndex = scene.childIndex(); - - if(isStacked){ - markParent.index = serIndex; - mark.index = catIndex; - } else { - markParent.index = catIndex; - mark.index = serIndex; - } - - return v1f.call(mark, scene.vars.value.rawValue); - }; - }; - } - - me.pvBarPanel = new pvc.visual.Panel(me, me.pvPanel, { - panelType: pv.Layout.Band, - extensionId: 'panel' - }) - .lock('layers', rootScene.childNodes) // series -> categories - .lockMark('values', function(seriesScene){ return seriesScene.childNodes; }) - .lockMark('orient', isVertical ? 'bottom-left' : 'left-bottom') - .lockMark('layout', isStacked ? 'stacked' : 'grouped') - .lockMark('verticalMode', me._barVerticalMode()) - .lockMark('yZero', orthoZero) - .pvMark - .band // categories - .x(sceneBaseScale) - .w(bandWidth) - .differentialControl(me._barDifferentialControl()) - .item - // Stacked Vertical bar charts show series from - // top to bottom (according to the legend) - .order(reverseSeries ? "reverse" : null) - .h(function(scene){ - /* May be negative */ - var y = sceneOrthoScale(scene); - return y != null ? chart.animate(0, y - orthoZero) : null; - }) - .w(barWidth) - .horizontalRatio(barSizeRatio) - .verticalMargin(barStackedMargin) - .end - ; - - this.pvBar = new pvc.visual.Bar(me, me.pvBarPanel.item, { - extensionId: '', // with the prefix, it gets 'bar_' - freePosition: true, - wrapper: wrapper - }) - .lockDimensions() - .pvMark - .antialias(false) - ; - - if(plot.option('OverflowMarkersVisible')){ - this._addOverflowMarkers(wrapper); - } - - if(me.valuesVisible){ - me.pvBarLabel = new pvc.visual.Label( - me, - me.pvBar.anchor(me.valuesAnchor || 'center'), - { - extensionId: 'label', - wrapper: wrapper - }) - .pvMark - .visible(function() { //no space for text otherwise - // this === pvMark - var length = this.scene.target[this.index][isVertical ? 'height' : 'width']; - - // Too small a bar to show any value? - return length >= 4; - }) - .font(me.valuesFont) // default - .text(function(scene){ - return scene.format(me.valuesMask); - }) - ; - } - }, - - /** - * Called to obtain the bar verticalMode property value. - * If it returns a function, - * - * that function will be called once. - * @virtual - */ - _barVerticalMode: function(){ - return null; - }, - - /** - * Called to obtain the bar differentialControl property value. - * If it returns a function, - * that function will be called once per category, - * on the first series. - * @virtual - */ - _barDifferentialControl: function(){ - return null; - }, - - _getV1Datum: function(scene){ - // Ensure V1 tooltip function compatibility - var datum = scene.datum; - if(datum){ - var datumEx = Object.create(datum); - datumEx.percent = scene.vars.value.percent; - datum = datumEx; - } - - return datum; - }, - - _addOverflowMarkers: function(wrapper){ - var orthoAxis = this.axes.ortho; - if(orthoAxis.option('FixedMax') != null){ - this.pvOverflowMarker = this._addOverflowMarker(false, orthoAxis.scale, wrapper); - } - - if(orthoAxis.option('FixedMin') != null){ - this.pvUnderflowMarker = this._addOverflowMarker(true, orthoAxis.scale, wrapper); - } - }, - - _addOverflowMarker: function(isMin, orthoScale, wrapper){ - /* NOTE: pv.Bar is not a panel, - * and as such markers will be children of bar's parent, - * yet have bar's anchor as a prototype. - */ - - var isVertical = this.isOrientationVertical(), - a_bottom = isVertical ? "bottom" : "left", - a_top = this.anchorOpposite(a_bottom), - a_height = this.anchorOrthoLength(a_bottom), - a_width = this.anchorLength(a_bottom), - paddings = this._layoutInfo.paddings, - rOrthoBound = isMin ? - (orthoScale.min - paddings[a_bottom]) : - (orthoScale.max + paddings[a_top]), - angle; - - if(!isMin){ - angle = isVertical ? Math.PI: -Math.PI/2; - } else { - angle = isVertical ? 0: Math.PI/2; - } - - return new pvc.visual.Dot( - this, - this.pvBar.anchor('center'), - { - noSelect: true, - noHover: true, - noClick: true, - noDoubleClick: true, - noTooltip: true, - freePosition: true, - extensionId: isMin ? 'underflowMarker' : 'overflowMarker', - wrapper: wrapper - }) - .intercept('visible', function(scene){ - var visible = this.delegateExtension(); - if(visible !== undefined && !visible){ - return false; - } - - var value = scene.vars.value.value; - if(value == null){ - return false; - } - - var targetInstance = this.pvMark.scene.target[this.index]; - - // Where is the position of the max of the bar? - var orthoMaxPos = targetInstance[a_bottom] + - (value > 0 ? targetInstance[a_height] : 0); - return isMin ? - (orthoMaxPos < rOrthoBound) : - (orthoMaxPos > rOrthoBound); - }) - .lock(a_top, null) - .lock('shapeSize') - .pvMark - .shape("triangle") - .shapeRadius(function(){ - return Math.min( - Math.sqrt(10), - this.scene.target[this.index][a_width] / 2); - }) - .shapeAngle(angle) - .lineWidth(1.5) - .strokeStyle("red") - .fillStyle("white") - [a_bottom](function(){ - return rOrthoBound + (isMin ? 1 : -1) * (this.shapeRadius() + 2); - }) - ; - }, - - /** - * Renders this.pvPanel - the parent of the marks that are affected by selection changes. - * @override - */ - renderInteractive: function(){ - this.pvPanel.render(); - }, - - /** - * Returns an array of marks whose instances are associated to a datum, or null. - * @override - */ - _getSelectableMarks: function(){ - return [this.pvBar]; - }, - - _buildScene: function(data, seriesData){ - var rootScene = new pvc.visual.Scene(null, {panel: this, group: data}); - - var categDatas = data._children; - var roles = this.visualRoles; - var valueVarHelper = new pvc.visual.RoleVarHelper(rootScene, roles.value, {hasPercentSubVar: this.stacked}); - var colorVarHelper = new pvc.visual.RoleVarHelper(rootScene, roles.color); - - /** - * Create starting scene tree - */ - seriesData - .children() - .each(createSeriesScene); - - return rootScene; - - function createSeriesScene(seriesData1){ - /* Create series scene */ - var seriesScene = new pvc.visual.Scene(rootScene, {group: seriesData1}), - seriesKey = seriesData1.key; - - seriesScene.vars.series = pvc.visual.ValueLabelVar.fromComplex(seriesData1); - - colorVarHelper.onNewScene(seriesScene, /* isLeaf */ false); - - categDatas.forEach(function(categData1){ - /* Create leaf scene */ - var group = data._childrenByKey[categData1.key]._childrenByKey[seriesKey], - scene = new pvc.visual.Scene(seriesScene, {group: group}); - - var categVar = - scene.vars.category = pvc.visual.ValueLabelVar.fromComplex(categData1); - - categVar.group = categData1; - - valueVarHelper.onNewScene(scene, /* isLeaf */ true); - colorVarHelper.onNewScene(scene, /* isLeaf */ true); - }); - } - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcBarChart.js b/pacotes/ccc2/pvc/pvcBarChart.js deleted file mode 100755 index 8b98155..0000000 --- a/pacotes/ccc2/pvc/pvcBarChart.js +++ /dev/null @@ -1,107 +0,0 @@ - -/** - * BarChart is the main class for generating... bar charts (another surprise!). - */ -def -.type('pvc.BarChart', pvc.BarAbstract) -.add({ - _animatable: true, - - _allowV1SecondAxis: true, - - _initPlotsCore: function(/*hasMultiRole*/){ - var options = this.options; - - var barPlot = new pvc.visual.BarPlot(this); - var trend = barPlot.option('Trend'); - - if(options.plot2){ - // Line Plot - var plot2Plot = new pvc.visual.PointPlot(this, { - name: 'plot2', - fixed: { - DataPart: '1' - }, - defaults: { - ColorAxis: 2, - LinesVisible: true, - DotsVisible: true - }}); - - if(!trend){ - trend = plot2Plot.option('Trend'); - } - } - - if(trend){ - // Trend Plot - new pvc.visual.PointPlot(this, { - name: 'trend', - fixed: { - DataPart: 'trend', - TrendType: 'none', - ColorRole: 'series', // one trend per series - NullInterpolatioMode: 'none' - }, - defaults: { - ColorAxis: 2, - LinesVisible: true, - DotsVisible: false - } - }); - } - }, - - _hasDataPartRole: function(){ - return true; - }, - - /** - * @override - */ - _createPlotPanels: function(parentPanel, baseOptions){ - var plots = this.plots; - - var barPlot = plots.bar; - var barPanel = new pvc.BarPanel( - this, - parentPanel, - barPlot, - Object.create(baseOptions)); - - // legacy field - this.barChartPanel = barPanel; - - var plot2Plot = plots.plot2; - if(plot2Plot){ - if(pvc.debug >= 3){ - this._log("Creating Point panel."); - } - - var pointPanel = new pvc.PointPanel( - this, - parentPanel, - plot2Plot, - Object.create(baseOptions)); - - // Legacy fields - barPanel.pvSecondLine = pointPanel.pvLine; - barPanel.pvSecondDot = pointPanel.pvDot; - - pointPanel._applyV1BarSecondExtensions = true; - } - - var trendPlot = plots.trend; - if(trendPlot){ - if(pvc.debug >= 3){ - this._log("Creating Trends Point panel."); - } - - new pvc.PointPanel( - this, - parentPanel, - trendPlot, - Object.create(baseOptions)); - } - } -}); diff --git a/pacotes/ccc2/pvc/pvcBarPanel.js b/pacotes/ccc2/pvc/pvcBarPanel.js deleted file mode 100755 index c5c27bb..0000000 --- a/pacotes/ccc2/pvc/pvcBarPanel.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Bar Panel. - */ -def -.type('pvc.BarPanel', pvc.BarAbstractPanel) -.add({ -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcBaseChart.axes.js b/pacotes/ccc2/pvc/pvcBaseChart.axes.js deleted file mode 100755 index 1f6d091..0000000 --- a/pacotes/ccc2/pvc/pvcBaseChart.axes.js +++ /dev/null @@ -1,337 +0,0 @@ -pvc.BaseChart -.add({ - /** - * An array of colors, represented as names, codes or {@link pv.Color} objects - * that is associated to each distinct value of the "color" visual role. - * - *

- * The legend panel associates each distinct dimension value to a color of {@link #colors}, - * following the dimension's natural order. - *

- *

- * The default dimension is the 'series' dimension. - *

- * - * @type (string|pv.Color)[] - */ - colors: null, - - /** - * A map of {@link pvc.visual.Axis} by axis id. - */ - axes: null, - axesList: null, - axesByType: null, - - _axisClassByType: { - 'color': pvc.visual.ColorAxis, - 'size': pvc.visual.SizeAxis, - 'base': pvc.visual.CartesianAxis, - 'ortho': pvc.visual.CartesianAxis - }, - - // 1 = root, 2 = leaf, 1|2=3 = everywhere - _axisCreateWhere: { - 'color': 1, - 'size': 2, - 'base': 3, - 'ortho': 3 - }, - - _axisCreationOrder: [ - 'color', - 'size', - 'base', - 'ortho' - ], - - _axisCreateIfUnbound: { - - }, - - _initAxes: function(hasMultiRole){ - this.axes = {}; - this.axesList = []; - this.axesByType = {}; - - // Clear any previous global color scales - delete this._rolesColorScale; - - // type -> index -> [datacell array] - // Used by sub classes. - var dataCellsByAxisTypeThenIndex; - if(!this.parent){ - dataCellsByAxisTypeThenIndex = {}; - - this.plotList.forEach(function(plot){ - this._collectPlotAxesDataCells(plot, dataCellsByAxisTypeThenIndex); - }, this); - - this._fixTrendsLabel(dataCellsByAxisTypeThenIndex); - } else { - dataCellsByAxisTypeThenIndex = this.root._dataCellsByAxisTypeThenIndex; - } - - // Used later in _bindAxes as well. - this._dataCellsByAxisTypeThenIndex = dataCellsByAxisTypeThenIndex; - - /* NOTE: Cartesian axes are created even when hasMultiRole && !parent - * because it is needed to read axis options in the root chart. - * Also binding occurs to be able to know its scale type. - * Yet, their scales are not setup at the root level. - */ - - // 1 = root, 2 = leaf, 1 | 2 = 3 = everywhere - var here = 0; - // Root? - if(!this.parent){ - here |= 1; - } - // Leaf? - if(this.parent || !hasMultiRole){ - here |= 2; - } - - // Used later in _bindAxes as well. - this._axisCreateHere = here; - - this._axisCreationOrder.forEach(function(type){ - // Create **here** ? - if((this._axisCreateWhere[type] & here) !== 0){ - var AxisClass; - var dataCellsByAxisIndex = dataCellsByAxisTypeThenIndex[type]; - if(dataCellsByAxisIndex){ - - AxisClass = this._axisClassByType[type]; - if(AxisClass){ - dataCellsByAxisIndex.forEach(function(dataCells, axisIndex){ - - new AxisClass(this, type, axisIndex); - - }, this); - } - } else if(this._axisCreateIfUnbound[type]){ - AxisClass = this._axisClassByType[type]; - if(AxisClass){ - new AxisClass(this, type, 0); - } - } - } - }, this); - - if(this.parent){ - // Copy axes that exist in root and not here - this.root.axesList.forEach(function(axis){ - if(!def.hasOwn(this.axes, axis.id)){ - this._addAxis(axis); - } - }, this); - } - }, - - _fixTrendsLabel: function(dataCellsByAxisTypeThenIndex){ - // Pre-register the label of the first trend type - // in the "trend" data part atom, cause in multi-charts - // an empty label would be registered first... - // We end up using this to - // allow to specify an alternate label for the trend. - var dataPartDimName = this._getDataPartDimName(); - if(dataPartDimName){ - // Find the first data cell with a trend type - var firstDataCell = def - .query(def.ownKeys(dataCellsByAxisTypeThenIndex)) - .selectMany(function(axisType){ - return dataCellsByAxisTypeThenIndex[axisType]; - }) - .selectMany() - .first (function(dataCell){ return !!dataCell.trend; }) - ; - - if(firstDataCell){ - var trendInfo = pvc.trends.get(firstDataCell.trend.type); - var dataPartAtom = trendInfo.dataPartAtom; - var trendLabel = firstDataCell.trend.label; - if(trendLabel === undefined){ - trendLabel = dataPartAtom.f; - } - - this._firstTrendAtomProto = { - v: dataPartAtom.v, - f: trendLabel - }; - } else { - delete this._firstTrendAtomProto; - } - } - }, - - /** - * Adds an axis to the chart. - * - * @param {pvc.visual.Axis} axis The axis. - * - * @type pvc.visual.Axis - */ - _addAxis: function(axis){ - - this.axes[axis.id] = axis; - if(axis.chart === this){ - axis.axisIndex = this.axesList.length; - } - - this.axesList.push(axis); - - var typeAxes = def.array.lazy(this.axesByType, axis.type); - var typeIndex = typeAxes.count || 0; - axis.typeIndex = typeIndex; - typeAxes[axis.index] = axis; - if(!typeIndex){ - typeAxes.first = axis; - } - typeAxes.count = typeIndex + 1; - - // For child charts, that simply copy color axes - if(axis.type === 'color' && axis.isBound()){ - this._onColorAxisScaleSet(axis); - } - - return this; - }, - - _getAxis: function(type, index){ - var typeAxes = this.axesByType[type]; - if(typeAxes && index != null && (+index >= 0)){ - return typeAxes[index]; - } - }, - - _bindAxes: function(/*hasMultiRole*/){ - // Bind all axes with dataCells registered in #_dataCellsByAxisTypeThenIndex - // and which were created **here** - - var here = this._axisCreateHere; - - def - .eachOwn( - this._dataCellsByAxisTypeThenIndex, - function(dataCellsByAxisIndex, type){ - // Created **here** ? - if((this._axisCreateWhere[type] & here) !== 0){ - - dataCellsByAxisIndex.forEach(function(dataCells, index){ - - var axisId = pvc.buildIndexedId(type, index); - var axis = this.axes[axisId]; - if(!axis.isBound()){ - axis.bind(dataCells); - } - - }, this); - } - }, - this); - }, - - _setAxesScales: function(/*isMulti*/){ - if(!this.parent){ - var colorAxes = this.axesByType.color; - if(colorAxes){ - colorAxes.forEach(function(axis){ - if(axis.isBound()){ - axis.calculateScale(); - this._onColorAxisScaleSet(axis); - } - }, this); - } - } - }, - - _onColorAxisScaleSet: function(axis){ - switch(axis.index){ - case 0: - this.colors = axis.scheme(); - break; - - case 1: - if(this._allowV1SecondAxis){ - this.secondAxisColor = axis.scheme(); - } - break; - } - }, - - /** - * Obtains an unified color scale, - * of all the color axes with specified colors. - * - * This color scale is used to satisfy axes - * with non-specified colors. - * - * Each color-role has a different unified color-scale, - * in order that the color keys are of the same types. - */ - _getRoleColorScale: function(roleName){ - return def.lazy( - def.lazy(this, '_rolesColorScale'), - roleName, - this._createRoleColorScale, this); - }, - - _createRoleColorScale: function(roleName){ - var firstScale, scale; - var valueToColorMap = {}; - - this.axesByType.color.forEach(function(axis){ - // Only use color axes with specified Colors - var axisRole = axis.role; - var isRoleCompatible = - (axisRole.name === roleName) || - (axisRole.sourceRole && axisRole.sourceRole.name === roleName); - - if(isRoleCompatible && - axis.scale && - (axis.index === 0 || - axis.option.isSpecified('Colors') || - axis.option.isSpecified('Map'))){ - - scale = axis.scale; - if(!firstScale){ firstScale = scale; } - - axis.domainValues.forEach(addDomainValue); - } - }, this); - - function addDomainValue(value){ - // First color wins - var key = '' + value; - if(!def.hasOwnProp.call(valueToColorMap, key)){ - valueToColorMap[key] = scale(value); - } - } - - if(!firstScale){ - return pvc.createColorScheme()(); - } - - scale = function(value){ - var key = '' + value; - if(def.hasOwnProp.call(valueToColorMap, key)){ - return valueToColorMap[key]; - } - - // creates a new entry... - var color = firstScale(value); - valueToColorMap[key] = color; - return color; - }; - - def.copy(scale, firstScale); // TODO: domain() and range() should be overriden... - - return scale; - }, - - _onLaidOut: function(){ - // NOOP - } -}); - diff --git a/pacotes/ccc2/pvc/pvcBaseChart.data.js b/pacotes/ccc2/pvc/pvcBaseChart.data.js deleted file mode 100755 index e697e6c..0000000 --- a/pacotes/ccc2/pvc/pvcBaseChart.data.js +++ /dev/null @@ -1,589 +0,0 @@ -pvc.BaseChart -.add({ - - /** - * The data that the chart is to show. - * @type pvc.data.Data - * @deprecated - */ - dataEngine: null, - - /** - * The data that the chart is to show. - * @type pvc.data.Data - */ - data: null, - - /** - * The resulting data of - * grouping {@link #data} by the data part role, - * when bound. - * - * @type pvc.data.Data - */ - _partData: null, - - - _visibleDataCache: null, - - /** - * The data source of the chart. - *

- * The {@link #data} of a root chart - * is loaded with the data in this array. - *

- * @type any[] - */ - resultset: [], - - /** - * The meta-data that describes each - * of the data components of {@link #resultset}. - * @type any[] - */ - metadata: [], - - _constructData: function(options) { - var parent = this.parent; - if(parent) { - this.dataEngine = - this.data = options.data || - def.fail.argumentRequired('options.data'); - } - }, - - _checkNoDataI: function(){ - // Child charts are created to consume *existing* data - if (!this.parent) { - - // If we don't have data, we just need to set a "no data" message - // and go on with life. - if(!this.allowNoData && this.resultset.length === 0) { - /*global NoDataException:true */ - throw new NoDataException(); - } - } - }, - - _checkNoDataII: function(){ - // Child charts are created to consume *existing* data - if (!this.parent) { - - // If we don't have data, we just need to set a "no data" message - // and go on with life. - if(!this.allowNoData && (!this.data || !this.data.count())) { - /*global NoDataException:true */ - throw new NoDataException(); - } - } - }, - - /** - * Initializes the data engine and roles - */ - _initData: function(keyArgs) { - if(!this.parent) { - var data = this.data; - if(!data || def.get(keyArgs, 'reloadData', true)) { - this._onLoadData(); - } else { - data.clearVirtuals(); - data.disposeChildren(); - } - } - - delete this._partData; - delete this._visibleDataCache; - - if(pvc.debug >= 3){ - this._log(this.data.getInfo()); - } - }, - - _onLoadData: function(){ - var data = this.data; - var options = this.options; - var dataPartDimName = this._getDataPartDimName(); - var complexTypeProj = this._complexTypeProj; - var translOptions = this._createTranslationOptions(dataPartDimName); - var translation = this._createTranslation(translOptions); - - if(pvc.debug >= 3){ - translation.logSource(); - } - - if(!data){ - // Now the translation can also configure the type - translation.configureType(); - - // If the the dataPart dimension isn't being read or calculated - // its value must be defaulted to 0. - if(dataPartDimName && !complexTypeProj.isReadOrCalc(dataPartDimName)){ - this._addDefaultDataPartCalculation(dataPartDimName); - } - } - - // ---------- - // Roles are bound before actually loading data. - // i) roles add default properties to dimensions bound to them - // ii) in order to be able to filter datums - // whose "every dimension in a measure role is null". - // - // TODO: check why PRE is done only on createVersion 1 and this one - // is done on every create version - this._bindVisualRolesPostI(); - - // Setup the complex type from complexTypeProj; - var complexType; - if(!data){ - complexType = new pvc.data.ComplexType(); - complexTypeProj.configureComplexType(complexType, translOptions); - } else { - complexType = data.type; - } - - this._bindVisualRolesPostII(complexType); - - if(pvc.debug >= 10){ - this._log(complexType.describe()); - } - - if(pvc.debug >= 3){ - this._logVisualRoles(); - } - - // ---------- - - if(!data) { - data = - this.dataEngine = // V1 property - this.data = new pvc.data.Data({ - type: complexType, - labelSep: options.groupedLabelSep - }); - } // else TODO: assert complexType has not changed... - - // ---------- - - var loadKeyArgs = { - where: this._getLoadFilter(), - isNull: this._getIsNullDatum() - }; - - var resultQuery = translation.execute(data); - - data.load(resultQuery, loadKeyArgs); - }, - - _createComplexTypeProject: function(){ - var options = this.options; - var complexTypeProj = new pvc.data.ComplexTypeProject(options.dimensionGroups); - - // Add specified dimensions - var userDimsSpec = options.dimensions; - for(var dimName in userDimsSpec) { // userDimsSpec can be null; 'for' accepts null! - complexTypeProj.setDim(dimName, userDimsSpec[dimName]); - } - - // Add data part dimension and - // dataPart calculation from series values - var dataPartDimName = this._getDataPartDimName(); - if(dataPartDimName){ - complexTypeProj.setDim(dataPartDimName); - - this._addPlot2SeriesDataPartCalculation(complexTypeProj, dataPartDimName); - } - - // Add specified calculations - var calcSpecs = options.calculations; - if(calcSpecs){ - calcSpecs.forEach(function(calcSpec){ - complexTypeProj.setCalc(calcSpec); - }); - } - - return complexTypeProj; - }, - - _getLoadFilter: function(){ - if(this.options.ignoreNulls) { - var me = this; - return function(datum){ - var isNull = datum.isNull; - - if(isNull && pvc.debug >= 4){ - me._info("Datum excluded."); - } - - return !isNull; - }; - } - }, - - _getIsNullDatum: function(){ - var measureDimNames = this.measureDimensionsNames(), - M = measureDimNames.length; - if(M) { - // Must have at least one measure role dimension not-null - return function(datum){ - var atoms = datum.atoms; - for(var i = 0 ; i < M ; i++){ - if(atoms[measureDimNames[i]].value != null){ - return false; - } - } - - return true; - }; - } - }, - - _createTranslation: function(translOptions){ - var TranslationClass = this._getTranslationClass(translOptions); - - return new TranslationClass(this, this._complexTypeProj, this.resultset, this.metadata, translOptions); - }, - - _getTranslationClass: function(translOptions){ - return translOptions.crosstabMode ? - pvc.data.CrosstabTranslationOper : - pvc.data.RelationalTranslationOper; - }, - - _createTranslationOptions: function(dataPartDimName){ - var options = this.options; - - var dataOptions = options.dataOptions || {}; - - var dataSeparator = options.dataSeparator; - if(dataSeparator === undefined){ - dataSeparator = dataOptions.separator; - } - - var dataMeasuresInColumns = options.dataMeasuresInColumns; - if(dataMeasuresInColumns === undefined){ - dataMeasuresInColumns = dataOptions.measuresInColumns; - } - - var dataCategoriesCount = options.dataCategoriesCount; - if(dataCategoriesCount === undefined){ - dataCategoriesCount = dataOptions.categoriesCount; - } - - var plot2 = options.plot2; - - var valueFormat = options.valueFormat, - valueFormatter; - if(valueFormat && valueFormat !== this.defaults.valueFormat){ - valueFormatter = function(v) { - return v != null ? valueFormat(v) : ""; - }; - } - - var secondAxisIdx; - if(plot2 && this._allowV1SecondAxis && (this.compatVersion() <= 1)){ - secondAxisIdx = pvc.parseDistinctIndexArray(options.secondAxisIdx) || -1; - } - - return { - compatVersion: this.compatVersion(), - plot2SeriesIndexes: secondAxisIdx, - seriesInRows: options.seriesInRows, - crosstabMode: options.crosstabMode, - isMultiValued: options.isMultiValued, - dataPartDimName: dataPartDimName, - dimensionGroups: options.dimensionGroups, - dimensions: options.dimensions, - readers: options.readers, - - measuresIndexes: options.measuresIndexes, // relational multi-valued - - multiChartIndexes: options.multiChartIndexes, - - // crosstab - separator: dataSeparator, - measuresInColumns: dataMeasuresInColumns, - categoriesCount: dataCategoriesCount, - - // TODO: currently measuresInRows is not implemented... - measuresIndex: dataOptions.measuresIndex || dataOptions.measuresIdx, // measuresInRows - measuresCount: dataOptions.measuresCount || dataOptions.numMeasures, // measuresInRows - - // Timeseries *parse* format - isCategoryTimeSeries: options.timeSeries, - - timeSeriesFormat: options.timeSeriesFormat, - valueNumberFormatter: valueFormatter - }; - }, - - _addPlot2SeriesDataPartCalculation: function(complexTypeProj, dataPartDimName){ - if(this.compatVersion() <= 1){ - return; - } - - var options = this.options; - var serRole = this._serRole; - - var plot2Series = (serRole != null) && - options.plot2 && - options.plot2Series && - def.array.as(options.plot2Series); - if(!plot2Series || !plot2Series.length){ - return; - } - - var inited = false; - var plot2SeriesSet = def.query(plot2Series).uniqueIndex(); - var dimNames, dataPartDim, part1Atom, part2Atom; - - complexTypeProj.setCalc({ - names: dataPartDimName, - - calculation: function(datum, atoms){ - if(!inited){ - // LAZY init - if(serRole.isBound()){ - dimNames = serRole.grouping.dimensionNames(); - dataPartDim = datum.owner.dimensions(dataPartDimName); - } - inited = true; - } - - if(dataPartDim){ - var seriesKey = pvc.data.Complex.values(datum, dimNames).join(','); - - atoms[dataPartDimName] = - def.hasOwnProp.call(plot2SeriesSet, seriesKey) ? - (part2Atom || (part2Atom = dataPartDim.intern("1"))) : - (part1Atom || (part1Atom = dataPartDim.intern("0"))); - } - } - }); - }, - - _addDefaultDataPartCalculation: function(dataPartDimName){ - var dataPartDim, part1Atom; - - this._complexTypeProj.setCalc({ - names: dataPartDimName, - - calculation: function(datum, atoms){ - if(!dataPartDim){ - dataPartDim = datum.owner.dimensions(dataPartDimName); - } - - atoms[dataPartDimName] = part1Atom || - (part1Atom = dataPartDim.intern("0")); - } - }); - }, - - partData: function(dataPartValues){ - if(!this._partData){ - if(!this._dataPartRole || !this._dataPartRole.grouping){ - /* Undefined or unbound */ - return this._partData = this.data; - } - - // Visible and not - this._partData = this.data.flattenBy(this._dataPartRole); - } - - if(!dataPartValues || !this._dataPartRole || !this._dataPartRole.grouping){ - return this._partData; - } - - var dataPartDimName = this._dataPartRole.firstDimensionName(); - - if(def.array.is(dataPartValues)){ - if(dataPartValues.length > 1){ - return this._partData.where([ - def.set({}, dataPartDimName, dataPartValues) - ]); - } - - dataPartValues = dataPartValues[0]; - } - - // TODO: should, at least, call some static method of Atom to build a global key - var child = this._partData._childrenByKey[/*dataPartDimName + ':' +*/ dataPartValues + '']; - if(!child){ - // NOTE: - // This helps, at least, the ColorAxis.dataCells setting - // the .data property, in a time where there aren't yet any datums of - // the 'trend' data part value. - // So we create a dummy empty place-holder child here, - // so that when the trend datums are added they end up here, - // and not in another new Data... - var dataPartCell = { - v: dataPartValues - }; - - // TODO: HACK: To make trend label fixing work in multi-chart scenarios... - if(dataPartValues === 'trend'){ - var firstTrendAtom = this._firstTrendAtomProto; - if(firstTrendAtom){ - dataPartCell.f = firstTrendAtom.f; - } - } - - child = new pvc.data.Data({ - parent: this._partData, - atoms: def.set({}, dataPartDimName, dataPartCell), - dimNames: [dataPartDimName], - datums: [] - // TODO: index - }); - } - return child; - }, - - // -------------------- - - /* - * Obtains the chart's visible data - * grouped according to the charts "main grouping". - * - * @param {string|string[]} [dataPartValue=null] The desired data part value or values. - * @param {object} [keyArgs=null] Optional keyword arguments object. - * @param {boolean} [keyArgs.ignoreNulls=true] Indicates that null datums should be ignored. - * - * @type pvc.data.Data - */ - visibleData: function(dataPartValue, keyArgs){ - var ignoreNulls = def.get(keyArgs, 'ignoreNulls', true); - if(ignoreNulls && this.options.ignoreNulls){ - // If already globally ignoring nulls, there's no need to do it explicitly anywhere - ignoreNulls = false; - } - - keyArgs = keyArgs ? Object.create(keyArgs) : {}; - keyArgs.ignoreNulls = ignoreNulls; - - var key = ignoreNulls + '|' + dataPartValue, // relying on array.toString, when an array - data = def.getOwn(this._visibleDataCache, key); - if(!data) { - data = this._createVisibleData(dataPartValue, keyArgs); - if(data){ - (this._visibleDataCache || (this._visibleDataCache = {})) - [key] = data; - } - } - - return data; - }, - - /* - * Creates the chart's visible data - * grouped according to the charts "main grouping". - * - *

- * The default implementation groups data by series visual role. - *

- * - * @param {string|string[]} [dataPartValue=null] The desired data part value or values. - * - * @type pvc.data.Data - * @protected - * @virtual - */ - _createVisibleData: function(dataPartValue, keyArgs){ - var partData = this.partData(dataPartValue); - if(!partData){ - return null; - } - - var ignoreNulls = def.get(keyArgs, 'ignoreNulls'); - - return this._serRole && this._serRole.grouping ? - partData.flattenBy(this._serRole, {visible: true, isNull: ignoreNulls ? false : null}) : - partData; - }, - // -------------------- - - _generateTrends: function(){ - if(this._dataPartRole){ - - def - .query(def.own(this.axes)) - .selectMany(function(axis){ return axis.dataCells; }) - .where(function(dataCell){ return !!dataCell.trend; }) - .distinct(function(dataCell){ - return dataCell.role.name + '|' + - (dataCell.dataPartValue || ''); - }) - .each(this._generateTrendsDataCell, this); - } - }, - - _interpolate: function(){ - def - .query(def.own(this.axes)) - .selectMany(function(axis){ return axis.dataCells; }) - .where(function(dataCell){ - var nim = dataCell.nullInterpolationMode; - return !!nim && nim !== 'none'; - }) - .distinct(function(dataCell){ - return dataCell.role.name + '|' + - (dataCell.dataPartValue || ''); - }) - .each(this._interpolateDataCell, this); - }, - - _interpolateDataCell: function(dataCell){ - }, - - _generateTrendsDataCell: function(dataCell){ - }, - - // --------------- - - /** - * Method to set the data to the chart. - * Expected object is the same as what comes from the CDA: - * {metadata: [], resultset: []} - */ - setData: function(data, options) { - this.setResultset(data.resultset); - this.setMetadata(data.metadata); - - // TODO: Danger! - $.extend(this.options, options); - - return this; - }, - - /** - * Sets the resultset that will be used to build the chart. - */ - setResultset: function(resultset) { - /*jshint expr:true */ - !this.parent || def.fail.operationInvalid("Can only set resultset on root chart."); - - this.resultset = resultset; - if (!resultset.length) { - this._log("Warning: Resultset is empty"); - } - - return this; - }, - - /** - * Sets the metadata that, optionally, - * will give more information for building the chart. - */ - setMetadata: function(metadata) { - /*jshint expr:true */ - !this.parent || def.fail.operationInvalid("Can only set resultset on root chart."); - - this.metadata = metadata; - if (!metadata.length) { - this._log("Warning: Metadata is empty"); - } - - return this; - } -}); - diff --git a/pacotes/ccc2/pvc/pvcBaseChart.extension.js b/pacotes/ccc2/pvc/pvcBaseChart.extension.js deleted file mode 100755 index c0e704e..0000000 --- a/pacotes/ccc2/pvc/pvcBaseChart.extension.js +++ /dev/null @@ -1,154 +0,0 @@ -pvc.BaseChart -.add({ - - _processExtensionPoints: function(){ - var components; - if(!this.parent){ - var points = this.options.extensionPoints; - components = {}; - if(points){ - for(var p in points) { - var id, prop; - var splitIndex = p.indexOf("_"); - if(splitIndex > 0){ - id = p.substring(0, splitIndex); - prop = p.substr(splitIndex + 1); - if(id && prop){ - var component = def.getOwn(components, id) || - (components[id] = new def.OrderedMap()); - - component.add(prop, points[p]); - } - } - } - } - } else { - components = this.parent._components; - } - - this._components = components; - }, - - /** - * This is the method to be used for the extension points - * for the specific contents of the chart. already ge a pie - * chart! Goes through the list of options and, if it - * matches the prefix, execute that method on the mark. - * WARNING: It's the user's responsibility to make sure that - * unexisting methods don't blow this. - */ - extend: function(mark, ids, keyArgs){ - if(def.array.is(ids)){ - ids.forEach(function(id){ - this._extendCore(mark, id, keyArgs); - }, this); - } else { - this._extendCore(mark, ids, keyArgs); - } - }, - - _extendCore: function(mark, id, keyArgs) { - // if mark is null or undefined, skip - if (mark) { - var component = def.getOwn(this._components, id); - if(component){ - if(mark.borderPanel){ - mark = mark.borderPanel; - } - - var logOut = pvc.debug >= 3 ? [] : null; - var constOnly = def.get(keyArgs, 'constOnly', false); - var wrap = mark.wrap; - var keyArgs2 = {tag: pvc.extensionTag}; - var isRealMark = mark instanceof pv.Mark; - - component.forEach(function(v, m){ - // Not everything that is passed to 'mark' argument - // is actually a mark...(ex: scales) - // Not locked and - // Not intercepted and - if(mark.isLocked && mark.isLocked(m)){ - if(logOut) {logOut.push(m + ": locked extension point!");} - } else if(mark.isIntercepted && mark.isIntercepted(m)) { - if(logOut) {logOut.push(m + ":" + pvc.stringify(v) + " (controlled)");} - } else { - if(logOut) {logOut.push(m + ": " + pvc.stringify(v)); } - - // Extend object css and svg properties - if(v != null){ - var type = typeof v; - if(type === 'object'){ - if(m === 'svg' || m === 'css'){ - var v2 = mark.propertyValue(m); - if(v2){ - v = def.copy(v2, v); - } - } - } else if(isRealMark && (wrap || constOnly) && type === 'function'){ - if(constOnly){ - return; - } - - if(m !== 'add'){ // TODO: "add" extension idiom - any other exclusions? - v = wrap.call(mark, v, m); - } - } - } - - // Distinguish between mark methods and properties - if (typeof mark[m] === "function") { - if(m != 'add' && mark.intercept){ - mark.intercept(m, v, keyArgs2); - } else { - // Not really a mark or not a real protovis property - mark[m](v); - } - } else { - mark[m] = v; - } - } - }); - - if(logOut){ - if(logOut.length){ - this._log("Applying Extension Points for: '" + id + "'\n\t* " + logOut.join("\n\t* ")); - } else if(pvc.debug >= 5) { - this._log("No Extension Points for: '" + id + "'"); - } - } - } - } else if(pvc.debug >= 4){ - this._log("Applying Extension Points for: '" + id + "' (target mark does not exist)"); - } - }, - - /** - * Obtains the specified extension point. - */ - _getExtension: function(id, prop) { - var component; - if(!def.array.is(id)){ - component = def.getOwn(this._components, id); - if(component){ - return component.get(prop); - } - } else { - // Last extension points are applied last, so have priority... - var i = id.length - 1, value; - while(i >= 0){ - component = def.getOwn(this._components, id[i--]); - if(component && (value = component.get(prop)) !== undefined){ - return value; - } - } - } - }, - - _getConstantExtension: function(id, prop) { - var value = this._getExtension(id, prop); - if(!def.fun.is(value)){ - return value; - } - } -}); - diff --git a/pacotes/ccc2/pvc/pvcBaseChart.js b/pacotes/ccc2/pvc/pvcBaseChart.js deleted file mode 100755 index b2a5adc..0000000 --- a/pacotes/ccc2/pvc/pvcBaseChart.js +++ /dev/null @@ -1,785 +0,0 @@ -/** - * The main chart component - */ -def -.type('pvc.BaseChart', pvc.Abstract) -.init(function(options) { - var originalOptions = options; - - var parent = this.parent = def.get(options, 'parent') || null; - if(parent){ - /*jshint expr:true */ - options || def.fail.argumentRequired('options'); - } else { - options = def.mixin.copy({}, this.defaults, options); - } - - this.options = options; - - if(parent) { - this.root = parent.root; - this.smallColIndex = options.smallColIndex; // required for the logId msk, setup in base - this.smallRowIndex = options.smallRowIndex; - - this._tooltipEnabled = parent._tooltipEnabled; - this._tooltipOptions = parent._tooltipOptions; - } else { - this.root = this; - } - - this.base(); - - if(pvc.debug >= 3){ - this._info("NEW CHART\n" + pvc.logSeparator.replace(/-/g, '=') + - "\n DebugLevel: " + pvc.debug); - } - - /* DEBUG options */ - if(pvc.debug >= 3 && !parent && originalOptions){ - this._info("OPTIONS:\n", originalOptions); - if(pvc.debug >= 5){ - // Log also as text, for easy copy paste of options JSON - this._trace(pvc.stringify(options, {ownOnly: false, funs: true})); - } - } - - if(parent){ - parent._addChild(this); - } - - this._constructData(options); - this._constructVisualRoles(options); -}) -.add({ - /** - * Indicates if the chart has been disposed. - */ - _disposed: false, - - _animatable: false, - - /** - * The chart's parent chart. - * - *

- * The root chart has null as the value of its parent property. - *

- * - * @type pvc.BaseChart - */ - parent: null, - - /** - * The chart's child charts. - * - * @type pvc.BaseChart[] - */ - children: null, - - /** - * The chart's root chart. - * - *

- * The root chart has itself as the value of the root property. - *

- * - * @type pvc.BaseChart - */ - root: null, - - /** - * Indicates if the chart has been pre-rendered. - *

- * This field is set to false - * at the beginning of the {@link #_preRender} method - * and set to true at the end. - *

- *

- * When a chart is re-rendered it can, - * optionally, also repeat the pre-render phase. - *

- * - * @type boolean - */ - isPreRendered: false, - - /** - * The version value of the current/last creation. - * - *

- * This value is changed on each pre-render of the chart. - * It can be useful to invalidate cached information that - * is only valid for each creation. - *

- *

- * Version values can be compared using the identity operator ===. - *

- * - * @type any - */ - _createVersion: 0, - - /** - * A callback function that is called - * when the protovis' panel render is about to start. - * - *

- * Note that this is after the pre-render phase. - *

- * - *

- * The callback is called with no arguments, - * but having the chart instance as its context (this value). - *

- * - * @function - */ - renderCallback: undefined, - - /** - * Contains the number of pages that a multi-chart contains - * when rendered with the previous render options. - *

- * This property is updated after a render of a chart - * where the visual role "multiChart" is assigned and - * the option "multiChartPageIndex" has been specified. - *

- * - * @type number|null - */ - multiChartPageCount: null, - - /** - * Contains the currently rendered multi-chart page index, - * relative to the previous render options. - *

- * This property is updated after a render of a chart - * where the visual role "multiChart" is assigned and - * the option "multiChartPageIndex" has been specified. - *

- * - * @type number|null - */ - multiChartPageIndex: null, - - left: 0, - top: 0, - - width: null, - height: null, - margins: null, - paddings: null, - - _allowV1SecondAxis: false, - - //------------------ - compatVersion: function(options){ - return (options || this.options).compatVersion; - }, - - _createLogInstanceId: function(){ - return "" + - this.constructor + this._createLogChildSuffix(); - }, - - _createLogChildSuffix: function(){ - return this.parent ? - (" (" + (this.smallRowIndex + 1) + "," + - (this.smallColIndex + 1) + ")") : - ""; - }, - - _addChild: function(childChart){ - /*jshint expr:true */ - (childChart.parent === this) || def.assert("Not a child of this chart."); - - this.children.push(childChart); - }, - - /** - * Building the visualization is made in 2 stages: - * First, the {@link #_preRender} method prepares and builds - * every object that will be used. - * - * Later the {@link #render} method effectively renders. - */ - _preRender: function(keyArgs) { - this._preRenderPhase1(keyArgs); - this._preRenderPhase2(keyArgs); - }, - - _preRenderPhase1: function(keyArgs) { - /* Increment pre-render version to allow for cache invalidation */ - this._createVersion++; - - this.isPreRendered = false; - - if(pvc.debug >= 3){ - this._log("Prerendering"); - } - - this.children = []; - - if (!this.parent) { - // Now's as good a time as any to completely clear out all - // tipsy tooltips - pvc.removeTipsyLegends(); - } - - /* Options may be changed between renders */ - this._processOptions(); - - /* Any data exists or throws - * (must be done AFTER processing options - * because of width, height properties and noData extension point...) - */ - this._checkNoDataI(); - - /* Initialize root visual roles */ - if(!this.parent && this._createVersion === 1) { - this._initVisualRoles(); - - this._bindVisualRolesPreI(); - - this._complexTypeProj = this._createComplexTypeProject(); - - this._bindVisualRolesPreII(); - } - - /* Initialize the data (and _bindVisualRolesPost) */ - this._initData(keyArgs); - - /* When data is excluded, there may be no data after all */ - this._checkNoDataII(); - - var hasMultiRole = this._isRoleAssigned('multiChart'); - - /* Initialize plots */ - this._initPlots(hasMultiRole); - - /* Initialize axes */ - this._initAxes(hasMultiRole); - this._bindAxes(hasMultiRole); - - /* Trends and Interpolation */ - if(this.parent || !hasMultiRole){ - // Interpolated data affects generated trends - this._interpolate(hasMultiRole); - - this._generateTrends(hasMultiRole); - } - - /* Set axes scales */ - this._setAxesScales(hasMultiRole); - }, - - _preRenderPhase2: function(/*keyArgs*/){ - var hasMultiRole = this._isRoleAssigned('multiChart'); - - /* Initialize chart panels */ - this._initChartPanels(hasMultiRole); - - this.isPreRendered = true; - }, - - // -------------- - - _setSmallLayout: function(keyArgs){ - if(keyArgs){ - var basePanel = this.basePanel; - - if(this._setProp('left', keyArgs) | this._setProp('top', keyArgs)){ - if(basePanel) { - def.set( - basePanel.position, - 'left', this.left, - 'top', this.top); - } - } - - if(this._setProp('width', keyArgs) | this._setProp('height', keyArgs)){ - if(basePanel){ - basePanel.size = new pvc.Size (this.width, this.height); - } - } - - if(this._setProp('margins', keyArgs) && basePanel){ - basePanel.margins = new pvc.Sides(this.margins); - } - - if(this._setProp('paddings', keyArgs) && basePanel){ - basePanel.paddings = new pvc.Sides(this.paddings); - } - } - }, - - _setProp: function(p, keyArgs){ - var v = keyArgs[p]; - if(v != null){ - this[p] = v; - return true; - } - }, - - // -------------- - - /** - * Processes options after user options and defaults have been merged. - * Applies restrictions, - * performs validations and - * options values implications. - * - * @author Alterado por Edmar Moretti para a SAGE - */ - _processOptions: function(){ - - var options = this.options; - //verifica se esta em porcentagem - if(parseInt(options.width,10)+"%" == options.width){ - try{ - var viewportwidth,viewportheight,wdiv,r, - scr = null, - inn = null, - wNoScroll = 0, - wScroll = 0;; - // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight - if (typeof window.innerWidth != 'undefined') - { - viewportwidth = window.innerWidth, - viewportheight = window.innerHeight; - } - // IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document) - else if (typeof document.documentElement != 'undefined' - && typeof document.documentElement.clientWidth != - 'undefined' && document.documentElement.clientWidth != 0) - { - viewportwidth = document.documentElement.clientWidth, - viewportheight = document.documentElement.clientHeight; - } - // older versions of IE - else - { - viewportwidth = document.getElementsByTagName('body')[0].clientWidth, - viewportheight = document.getElementsByTagName('body')[0].clientHeight; - } - //scroller - scr = document.createElement('div'); - scr.style.position = 'absolute'; - scr.style.top = '-1000px'; - scr.style.left = '-1000px'; - scr.style.width = '100px'; - scr.style.height = '50px'; - // Start with no scrollbar - scr.style.overflow = 'hidden'; - // Inner content div - inn = document.createElement('div'); - inn.style.width = '100%'; - inn.style.height = '200px'; - // Put the inner div in the scrolling div - scr.appendChild(inn); - // Append the scrolling div to the doc - document.body.appendChild(scr); - // Width of the inner div sans scrollbar - wNoScroll = inn.offsetWidth; - // Add the scrollbar - scr.style.overflow = 'auto'; - // Width of the inner div width scrollbar - wScroll = inn.offsetWidth; - // Remove the scrolling div from the doc - document.body.removeChild(document.body.lastChild); - // Pixel width of the scroller - viewportwidth = viewportwidth - (wNoScroll - wScroll); - r = (parseInt(options.width,10) / 100) * viewportwidth; - options.width = parseInt(r,10); - } - catch(e){ - options.width = parseInt(options.width,10); - } - - } - if(!this.parent){ - this.width = options.width; - this.height = options.height; - this.margins = options.margins; - this.paddings = options.paddings; - } - - if(this.compatVersion() <= 1){ - options.plot2 = this._allowV1SecondAxis && !!options.secondAxis; - } - - this._processOptionsCore(options); - - this._processExtensionPoints(); - - return options; - }, - - /** - * Processes options after user options and default options have been merged. - * Override to apply restrictions, perform validation or - * options values implications. - * When overriden, the base implementation should be called. - * The implementation must be idempotent - - * its successive application should yield the same results. - * @virtual - */ - _processOptionsCore: function(options){ - // Disable animation if environment doesn't support it - if(!this.parent){ - if (!$.support.svg || pv.renderer() === 'batik') { - options.animate = false; - } - - this._processTooltipOptions(options); - } - }, - - _tooltipDefaults: { - gravity: 's', - delayIn: 200, - delayOut: 80, // smoother moving between marks with tooltips, possibly slightly separated - offset: 2, - opacity: 0.9, - html: true, - fade: true, - useCorners: false, - arrowVisible: true, - followMouse: false, - format: undefined - }, - - _processTooltipOptions: function(options){ - var isV1Compat = this.compatVersion() <= 1; - - var tipOptions = options.tooltip; - var tipEnabled = options.tooltipEnabled; - if(tipEnabled == null){ - if(tipOptions){ - tipEnabled = tipOptions.enabled; - } - - if(tipEnabled == null){ - if(isV1Compat){ - tipEnabled = options.showTooltips; - } - - if(tipEnabled == null){ - tipEnabled = true; - } - } - } - - if(tipEnabled){ - if(!tipOptions){ - tipOptions = {}; - } - - if(isV1Compat){ - this._importV1TooltipOptions(tipOptions, options); - } - - def.eachOwn(this._tooltipDefaults, function(dv, p){ - var value = options['tooltip' + def.firstUpperCase(p)]; - if(value !== undefined){ - tipOptions[p] = value; - } else if(tipOptions[p] === undefined){ - tipOptions[p] = dv; - } - }); - } else { - tipOptions = {}; - } - - this._tooltipEnabled = tipEnabled; - this._tooltipOptions = tipOptions; - }, - - _importV1TooltipOptions: function(tipOptions, options){ - var v1TipOptions = options.tipsySettings; - if(v1TipOptions){ - this.extend(v1TipOptions, "tooltip"); - - for(var p in v1TipOptions){ - if(tipOptions[p] === undefined){ - tipOptions[p] = v1TipOptions[p]; - } - } - - // Force V1 html default - if(tipOptions.html == null){ - tipOptions.html = false; - } - } - }, - - // -------------- - - /** - * Render the visualization. - * If not pre-rendered, do it now. - */ - render: function(bypassAnimation, recreate, reloadData){ - var hasError; - - /*global console:true*/ - if(pvc.debug > 1){ - pvc.group("CCC RENDER"); - } - - // Don't let selection change events to fire before the render is finished - this._suspendSelectionUpdate(); - try{ - this.useTextMeasureCache(function(){ - try{ - if (!this.isPreRendered || recreate){ - this._preRender({reloadData: reloadData}); - } else if(!this.parent && this.isPreRendered){ - pvc.removeTipsyLegends(); - } - - this.basePanel.render({ - bypassAnimation: bypassAnimation, - recreate: recreate - }); - - } catch (e) { - /*global NoDataException:true*/ - if (e instanceof NoDataException) { - if(pvc.debug > 1){ - this._log("No data found."); - } - - this._addErrorPanelMessage("No data found", true); - } else { - hasError = true; - - // We don't know how to handle this - pvc.logError(e.message); - - if(pvc.debug > 0){ - this._addErrorPanelMessage("Error: " + e.message, false); - } - //throw e; - } - } - }); - } finally { - if(!hasError){ - this._resumeSelectionUpdate(); - } - - if(pvc.debug > 1){ - pvc.groupEnd(); - } - } - - return this; - }, - - _addErrorPanelMessage: function(text, isNoData){ - var options = this.options, - pvPanel = new pv.Panel() - .canvas(options.canvas) - .width(this.width) - .height(this.height), - pvMsg = pvPanel.anchor("center").add(pv.Label) - .text(text); - - if(isNoData){ - this.extend(pvMsg, "noDataMessage"); - } - - pvPanel.render(); - }, - - useTextMeasureCache: function(fun, ctx){ - var root = this.root; - var textMeasureCache = root._textMeasureCache || - (root._textMeasureCache = pv.Text.createCache()); - - return pv.Text.usingCache(textMeasureCache, fun, ctx || this); - }, - - /** - * Animation - */ - animate: function(start, end) { - return this.basePanel.animate(start, end); - }, - - /** - * Indicates if the chart is currently - * rendering the animation start phase. - *

- * Prefer using this function instead of {@link #animate} - * whenever its start or end arguments - * involve a non-trivial calculation. - *

- * - * @type boolean - */ - isAnimatingStart: function() { - return this.basePanel.isAnimatingStart(); - }, - - isOrientationVertical: function(orientation) { - return (orientation || this.options.orientation) === pvc.orientation.vertical; - }, - - isOrientationHorizontal: function(orientation) { - return (orientation || this.options.orientation) === pvc.orientation.horizontal; - }, - - /** - * Disposes the chart, any of its panels and child charts. - */ - dispose: function(){ - if(!this._disposed){ - - // TODO: - - this._disposed = true; - } - }, - - defaults: { -// canvas: null, - - width: 400, - height: 300, - -// margins: undefined, -// paddings: undefined, -// contentMargins: undefined, -// contentPaddings: undefined, -// leafContentOverflow: 'auto', -// multiChartMax: undefined, -// multiChartColumnsMax: undefined, -// multiChartSingleRowFillsHeight: undefined, -// multiChartSingleColFillsHeight: undefined, - -// smallWidth: undefined, -// smallHeight: undefined, -// smallAspectRatio: undefined, -// smallMargins: undefined, -// smallPaddings: undefined, - -// smallContentMargins: undefined, -// smallContentPaddings: undefined, -// smallTitlePosition: undefined, -// smallTitleAlign: undefined, -// smallTitleAlignTo: undefined, -// smallTitleOffset: undefined, -// smallTitleKeepInBounds: undefined, -// smallTitleSize: undefined, -// smallTitleSizeMax: undefined, -// smallTitleMargins: undefined, -// smallTitlePaddings: undefined, -// smallTitleFont: undefined, - - orientation: 'vertical', - -// extensionPoints: undefined, -// -// visualRoles: undefined, -// dimensions: undefined, -// dimensionGroups: undefined, -// calculations: undefined, -// readers: undefined, - - ignoreNulls: true, // whether to ignore or keep "null"-measure datums upon loading - crosstabMode: true, -// multiChartIndexes: undefined, - isMultiValued: false, - seriesInRows: false, - groupedLabelSep: undefined, -// measuresIndexes: undefined, -// dataOptions: undefined, -// dataSeparator -// dataMeasuresInColumns -// dataCategoriesCount - -// timeSeries: undefined, -// timeSeriesFormat: undefined, - - animate: true, - -// title: null, - - titlePosition: "top", // options: bottom || left || right - titleAlign: "center", // left / right / center -// titleAlignTo: undefined, -// titleOffset: undefined, -// titleKeepInBounds: undefined, -// titleSize: undefined, -// titleSizeMax: undefined, -// titleMargins: undefined, -// titlePaddings: undefined, -// titleFont: undefined, - - legend: false, // Show Legends - legendPosition: "bottom", -// legendFont: undefined, -// legendSize: undefined, -// legendSizeMax: undefined, -// legendAlign: undefined, -// legendAlignTo: undefined, -// legendOffset: undefined, -// legendKeepInBounds: undefined, -// legendMargins: undefined, -// legendPaddings: undefined, -// legendTextMargin: undefined, -// legendItemPadding: undefined, // ATTENTION: this is different from legendPaddings -// legendMarkerSize: undefined, - -// colors: null, - - v1StyleTooltipFormat: function(s, c, v, datum) { - return s + ", " + c + ": " + this.chart.options.valueFormat(v) + - (datum && datum.percent ? ( " (" + datum.percent.label + ")") : ""); - }, - - valueFormat: def.scope(function(){ - var pvFormat = pv.Format.number().fractionDigits(0, 2); - - return function(d) { - return pvFormat.format(d); - // pv.Format.number().fractionDigits(0, 10).parse(d)); - }; - }), - - /* For numeric values in percentage */ - percentValueFormat: def.scope(function(){ - var pvFormat = pv.Format.number().fractionDigits(0, 1); - - return function(d){ - return pvFormat.format(d * 100) + "%"; - }; - }), - - // Content/Plot area clicking - clickable: false, -// clickAction: null, -// doubleClickAction: null, - doubleClickMaxDelay: 300, //ms -// - hoverable: false, - - selectable: false, - selectionMode: 'rubberband', // focuswindow, // single (click-only) // custom (by code only) - //selectionCountMax: 0, // <= 0 -> no limit - -// selectionChangedAction: null, -// userSelectionAction: null, - - // Use CTRL key to make fine-grained selections - ctrlSelectMode: true, - clearSelectionMode: 'emptySpaceClick', // or null <=> 'manual' (i.e., by code) - -// renderCallback: undefined, - - compatVersion: Infinity // numeric, 1 currently recognized - } -}); - diff --git a/pacotes/ccc2/pvc/pvcBaseChart.panels.js b/pacotes/ccc2/pvc/pvcBaseChart.panels.js deleted file mode 100755 index 0731d67..0000000 --- a/pacotes/ccc2/pvc/pvcBaseChart.panels.js +++ /dev/null @@ -1,276 +0,0 @@ -pvc.BaseChart -.add({ - /** - * The base panel is the root container of a chart. - *

- * The base panel of a root chart is the top-most root container. - * It has {@link pvc.BasePanel#isTopRoot} equal to true. - *

- *

- * The base panel of a non-root chart is the root of the chart's panels, - * but is not the top-most root panel, over the charts hierarchy. - *

- * - * @type pvc.BasePanel - */ - basePanel: null, - - /** - * The panel that shows the chart's title. - *

- * This panel is the first child of {@link #basePanel} to be created. - * It is only created when the chart has a non-empty title. - *

- *

- * Being the first child causes it to occupy the - * whole length of the side of {@link #basePanel} - * to which it is docked. - *

- * - * @type pvc.TitlePanel - */ - titlePanel: null, - - /** - * The panel that shows the chart's main legend. - *

- * This panel is the second child of {@link #basePanel} to be created. - * There is an option to not show the chart's legend, - * in which case this panel is not created. - *

- * - *

- * The current implementation of the legend panel - * presents a discrete association of colors and labels. - *

- * - * @type pvc.LegendPanel - */ - legendPanel: null, - - /** - * The panel that hosts child chart's base panels. - * - * @type pvc.MultiChartPanel - */ - _multiChartPanel: null, - - _initChartPanels: function(hasMultiRole){ - /* Initialize chart panels */ - this._initBasePanel (); - this._initTitlePanel (); - - var legendPanel = this._initLegendPanel(); - - if(!this.parent && hasMultiRole) { - this._initMultiChartPanel(); - - if(legendPanel){ - this._initLegendScenes(legendPanel); - } - } else { - var options = this.options; - - if(legendPanel){ - this._initLegendScenes(legendPanel); - } - - this._preRenderContent({ - margins: hasMultiRole ? options.smallContentMargins : options.contentMargins, - paddings: hasMultiRole ? options.smallContentPaddings : options.contentPaddings, - clickAction: options.clickAction, - doubleClickAction: options.doubleClickAction - }); - } - }, - - /** - * Override to create chart specific content panels here. - * No need to call base. - * - * @param {object} contentOptions Object with content specific options. Can be modified. - * @param {pvc.Sides} [contentOptions.margins] The margins for the content panels. - * @param {pvc.Sides} [contentOptions.paddings] The paddings for the content panels. - * - * @virtual - */ - _preRenderContent: function(contentOptions){ - /* NOOP */ - }, - - /** - * Creates and initializes the base panel. - */ - _initBasePanel: function() { - var options = this.options; - var basePanelParent = this.parent && this.parent._multiChartPanel; - - this.basePanel = new pvc.BasePanel(this, basePanelParent, { - margins: this.margins, - paddings: this.paddings, - size: {width: this.width, height: this.height} - }); - }, - - /** - * Creates and initializes the title panel, - * if the title is specified. - */ - _initTitlePanel: function(){ - var options = this.options; - if (!def.empty(options.title)) { - var isRoot = !this.parent; - this.titlePanel = new pvc.TitlePanel(this, this.basePanel, { - title: options.title, - font: options.titleFont, - anchor: options.titlePosition, - align: options.titleAlign, - alignTo: options.titleAlignTo, - offset: options.titleOffset, - keepInBounds: options.titleKeepInBounds, - margins: options.titleMargins, - paddings: options.titlePaddings, - titleSize: options.titleSize, - titleSizeMax: options.titleSizeMax - }); - } - }, - - /** - * Creates and initializes the legend panel, - * if the legend is active. - */ - _initLegendPanel: function(){ - var options = this.options; - // global legend(s) switch - if (options.legend) { - - var legend = new pvc.visual.Legend(this, 'legend', 0); - - // TODO: pass all these options to Legend class - - this.legendPanel = new pvc.LegendPanel(this, this.basePanel, { - anchor: legend.option('Position'), - align: legend.option('Align'), - alignTo: options.legendAlignTo, - offset: options.legendOffset, - keepInBounds: options.legendKeepInBounds, - size: legend.option('Size'), - sizeMax: legend.option('SizeMax'), - margins: legend.option('Margins'), - paddings: legend.option('Paddings'), - font: legend.option('Font'), - scenes: def.getPath(options, 'legend.scenes'), - - // Bullet legend - textMargin: options.legendTextMargin, - itemPadding: options.legendItemPadding, - markerSize: options.legendMarkerSize - //shape: options.legendShape // TODO: <- doesn't this come from the various color axes? - }); - - return this.legendPanel; - } - }, - - _getLegendBulletRootScene: function(){ - return this.legendPanel && this.legendPanel._getBulletRootScene(); - }, - - /** - * Creates and initializes the multi-chart panel. - */ - _initMultiChartPanel: function(){ - var basePanel = this.basePanel; - var options = this.options; - - this._multiChartPanel = new pvc.MultiChartPanel( - this, - basePanel, - { - margins: options.contentMargins, - paddings: options.contentPaddings - }); - - this._multiChartPanel.createSmallCharts(); - - // BIG HACK: force legend to be rendered after the small charts, - // to allow them to register legend renderers. - basePanel._children.unshift(basePanel._children.pop()); - }, - - _coordinateSmallChartsLayout: function(scopesByType){ - // NOOP - }, - - /** - * Creates the legend group scenes of a chart. - * - * The default implementation creates - * one legend group per data part value - * and with one legend item per - * value of the "color" visual role. - * - * Legend groups are registered with the id prefix "part" - * followed by the corresponding part value. - */ - _initLegendScenes: function(legendPanel){ - - var rootScene, dataPartDimName; - var legendIndex = 0; // always start from 0 - - // For all color axes... - var colorAxes = this.axesByType.color; - if(colorAxes){ - colorAxes.forEach(processAxis, this); - } - - // ------------ - - function processAxis(colorAxis){ - if(colorAxis.option('LegendVisible')){ - var dataCells = colorAxis && colorAxis.dataCells; - if(dataCells){ - dataCells - .forEach(function(dataCell){ - if(dataCell.role.isDiscrete()){ - var domainData = dataCell.data; - - if(!rootScene){ - dataPartDimName = this._getDataPartDimName(); - rootScene = legendPanel._getBulletRootScene(); - } - - var dataPartAtom; - var locked = colorAxis.option('LegendClickMode') === 'toggleVisible' && - (dataPartAtom = domainData.atoms[dataPartDimName]) && - dataPartAtom.value === 'trend'; - - var groupScene = rootScene.createGroup({ - group: domainData, - colorAxis: colorAxis, - clickMode: locked ? 'none' : undefined, - extensionPrefix: pvc.buildIndexedId('', legendIndex++) - }); - - // For later binding an appropriate bullet renderer - dataCell.legendBulletGroupScene = groupScene; - - var partColorScale = colorAxis.scale; - - domainData - .children() - .each(function(itemData){ - var itemScene = groupScene.createItem({group: itemData}); - - // HACK... - itemScene.color = partColorScale(itemData.value); - }); - } - }, this); - } - } - } - } -}); - diff --git a/pacotes/ccc2/pvc/pvcBaseChart.plots.js b/pacotes/ccc2/pvc/pvcBaseChart.plots.js deleted file mode 100755 index e64b556..0000000 --- a/pacotes/ccc2/pvc/pvcBaseChart.plots.js +++ /dev/null @@ -1,92 +0,0 @@ -pvc.BaseChart -.add({ - _initPlots: function(hasMultiRole){ - - this.plotPanelList = null; - - // reset plots - if(!this.parent){ - this.plots = {}; - this.plotList = []; - this.plotsByType = {}; - - this._initPlotsCore(hasMultiRole); - } else { - var root = this.root; - - this.plots = root.plots; - this.plotList = root.plotList; - this.plotsByType = root.plotsByType; - } - }, - - _initPlotsCore: function(/*hasMultiRole*/){ - // NOOP - }, - - _addPlot: function(plot){ - var plotsByType = this.plotsByType; - var plots = this.plots; - - var plotType = plot.type; - var plotIndex = plot.index; - var plotName = plot.name; - var plotId = plot.id; - - if(plotName && def.hasOwn(plots, plotName)){ - throw def.error.operationInvalid("Plot name '{0}' already taken.", [plotName]); - } - - if(def.hasOwn(plots, plotId)){ - throw def.error.operationInvalid("Plot id '{0}' already taken.", [plotId]); - } - - var typePlots = def.array.lazy(plotsByType, plotType); - if(def.hasOwn(typePlots, plotIndex)){ - throw def.error.operationInvalid("Plot index '{0}' of type '{1}' already taken.", [plotIndex, plotType]); - } - - plot.globalIndex = this.plotList.length; - typePlots[plotIndex] = plot; - this.plotList.push(plot); - plots[plotId] = plot; - if(plotName){ - plots[plotName] = plot; - } - }, - - _collectPlotAxesDataCells: function(plot, dataCellsByAxisTypeThenIndex){ - /* Configure Color Axis Data Cell */ - var colorRoleName = plot.option('ColorRole'); - if(colorRoleName){ - var colorRole = this.visualRoles(colorRoleName); - if(colorRole.isBound()){ - var colorDataCellsByAxisIndex = - def - .array - .lazy(dataCellsByAxisTypeThenIndex, 'color'); - - def - .array - .lazy(colorDataCellsByAxisIndex, plot.option('ColorAxis') - 1) - .push({ - plot: plot, - role: colorRole, - dataPartValue: plot.option('DataPart') - }); - } - } - }, - - // Called by the pvc.PlotPanel class - _addPlotPanel: function(plotPanel){ - def.lazy(this, 'plotPanels')[plotPanel.plot.id] = plotPanel; - def.array.lazy(this, 'plotPanelList').push(plotPanel); - }, - - /* @abstract */ - _createPlotPanels: function(/*parentPanel, baseOptions*/){ - throw def.error.notImplemented(); - } -}); - diff --git a/pacotes/ccc2/pvc/pvcBaseChart.selection.js b/pacotes/ccc2/pvc/pvcBaseChart.selection.js deleted file mode 100755 index deb11c4..0000000 --- a/pacotes/ccc2/pvc/pvcBaseChart.selection.js +++ /dev/null @@ -1,172 +0,0 @@ -pvc.BaseChart -.add({ - _updateSelectionSuspendCount: 0, - _lastSelectedDatums: null, - - /** - * Clears any selections and, if necessary, - * re-renders the parts of the chart that show selected marks. - * - * @type undefined - * @virtual - */ - clearSelections: function(){ - if(this.data.owner.clearSelected()) { - this.updateSelections(); - } - - return this; - }, - - _updatingSelections: function(method, context){ - this._suspendSelectionUpdate(); - - //var datums = this._lastSelectedDatums ? this._lastSelectedDatums.values() : []; - //this._log("Previous Datum count=" + datums.length + - // " keys=\n" + datums.map(function(d){return d.key;}).join('\n')); - - try { - method.call(context || this); - } finally { - this._resumeSelectionUpdate(); - } - }, - - _suspendSelectionUpdate: function(){ - if(this === this.root) { - this._updateSelectionSuspendCount++; - } else { - this.root._suspendSelectionUpdate(); - } - }, - - _resumeSelectionUpdate: function(){ - if(this === this.root) { - if(this._updateSelectionSuspendCount > 0) { - if(!(--this._updateSelectionSuspendCount)) { - this.updateSelections(); - } - } - } else { - this.root._resumeSelectionUpdate(); - } - }, - - /** - * Re-renders the parts of the chart that show marks. - * - * @type undefined - * @virtual - */ - updateSelections: function(keyArgs){ - if(this === this.root) { - if(this._inUpdateSelections) { - return this; - } - - if(this._updateSelectionSuspendCount) { - return this; - } - - var selectedChangedDatumMap = this._calcSelectedChangedDatums(); - if(!selectedChangedDatumMap){ - return; - } - - pvc.removeTipsyLegends(); - - // Reentry control - this._inUpdateSelections = true; - try { - // Fire action - var action = this.options.selectionChangedAction; - if(action){ - var selectedDatums = this.data.selectedDatums(); - var selectedChangedDatums = selectedChangedDatumMap.values(); - action.call( - this.basePanel._getContext(), - selectedDatums, - selectedChangedDatums); - } - - // Rendering afterwards allows the action to change the selection in between - if(def.get(keyArgs, 'render', true)){ - this.useTextMeasureCache(function(){ - this.basePanel.renderInteractive(); - }, this); - } - } finally { - this._inUpdateSelections = false; - } - } else { - this.root.updateSelections(); - } - - return this; - }, - - _calcSelectedChangedDatums: function(){ - // Capture currently selected datums - // Calculate the ones that changed. - var selectedChangedDatums; - var nowSelectedDatums = this.data.selectedDatumMap(); - var lastSelectedDatums = this._lastSelectedDatums; - if(!lastSelectedDatums){ - if(!nowSelectedDatums.count){ - return; - } - - selectedChangedDatums = nowSelectedDatums.clone(); - } else { - selectedChangedDatums = lastSelectedDatums.symmetricDifference(nowSelectedDatums); - if(!selectedChangedDatums.count){ - return; - } - } - - this._lastSelectedDatums = nowSelectedDatums; - - var datums = this._lastSelectedDatums ? this._lastSelectedDatums.values() : []; -// this._log("Now Datum count=" + datums.length + -// " keys=\n" + datums.map(function(d){return d.key;}).join('\n')); - - return selectedChangedDatums; - }, - - _onUserSelection: function(datums){ - if(!datums || !datums.length){ - return datums; - } - - if(this === this.root) { - // Fire action - var action = this.options.userSelectionAction; - if(action){ - return action.call(null, datums) || datums; - } - - return datums; - } - - return this.root._onUserSelection(datums); - }, - - _isSelectable: function(){ - return this.options.selectable; - }, - - _canSelectWithRubberband: function(){ - var options = this.options; - return options.selectable && options.selectionMode === 'rubberband'; - }, - - _canSelectWithClick: function(){ - return this._canSelectWithRubberband(); - }, - - _canSelectWithFocusWindow: function(){ - var options = this.options; - return options.selectable && options.selectionMode === 'focuswindow'; - } -}); - diff --git a/pacotes/ccc2/pvc/pvcBaseChart.visualRoles.js b/pacotes/ccc2/pvc/pvcBaseChart.visualRoles.js deleted file mode 100755 index 5ce8954..0000000 --- a/pacotes/ccc2/pvc/pvcBaseChart.visualRoles.js +++ /dev/null @@ -1,534 +0,0 @@ - -pvc.BaseChart -.add({ - /** - * A map of {@link pvc.visual.Role} by name. - * - * @type object - */ - _visualRoles: null, - _visualRoleList: null, - - _serRole: null, - _dataPartRole: null, - - /** - * An array of the {@link pvc.visual.Role} that are measures. - * - * @type pvc.visual.Role[] - */ - _measureVisualRoles: null, - - _constructVisualRoles: function(/*options*/) { - var parent = this.parent; - if(parent) { - this._visualRoles = parent._visualRoles; - this._visualRoleList = parent._visualRoleList; - this._measureVisualRoles = parent._measureVisualRoles; - - if(parent._multiChartRole) { - this._multiChartRole = parent._multiChartRole; - } - - if(parent._serRole) { - this._serRole = parent._serRole; - } - - if(parent._colorRole) { - this._colorRole = parent._colorRole; - } - - if(parent._dataPartRole) { - this._dataPartRole = parent._dataPartRole; - } - } else { - this._visualRoles = {}; - this._visualRoleList = []; - this._measureVisualRoles = []; - } - }, - - _hasDataPartRole: function(){ - return false; - }, - - _getSeriesRoleSpec: function(){ - return null; - }, - - _getColorRoleSpec: function(){ - return null; - }, - - _addVisualRole: function(name, keyArgs){ - keyArgs = def.set(keyArgs, 'index', this._visualRoleList.length); - - var visualRole = new pvc.visual.Role(name, keyArgs); - - this._visualRoleList.push(visualRole); - this._visualRoles[name] = visualRole; - if(visualRole.isMeasure){ - this._measureVisualRoles.push(visualRole); - } - return visualRole; - }, - - /** - * Initializes each chart's specific roles. - * @virtual - */ - _initVisualRoles: function(){ - this._multiChartRole = this._addVisualRole( - 'multiChart', - { - defaultDimension: 'multiChart*', - requireIsDiscrete: true - }); - - if(this._hasDataPartRole()){ - this._dataPartRole = this._addVisualRole( - 'dataPart', - { - defaultDimension: 'dataPart', - requireSingleDimension: true, - requireIsDiscrete: true, - dimensionDefaults: { - isHidden: true, - comparer: def.compare - } - }); - } - - var serRoleSpec = this._getSeriesRoleSpec(); - if(serRoleSpec){ - this._serRole = this._addVisualRole('series', serRoleSpec); - } - - var colorRoleSpec = this._getColorRoleSpec(); - if(colorRoleSpec){ - this._colorRole = this._addVisualRole('color', colorRoleSpec); - } - }, - - /** - * Binds visual roles to grouping specifications - * that have not yet been bound to and validated against a complex type. - * - * This allows inferring proper defaults to - * dimensions bound to roles, - * by taking them from the roles requirements. - */ - _bindVisualRolesPreI: function(){ - // Clear reversed status of visual roles - def.eachOwn(this._visualRoles, function(role){ - role.setIsReversed(false); - }); - - var sourcedRoles = []; - - // Process the visual roles with options - // It is important to process them in visual role definition order - // cause the processing that is done generally - // depends on the processing order; - // A chart definition must behave the same - // in every environment, independently of the order in which - // object properties are enumerated. - var options = this.options; - var roleOptions = options.visualRoles; - - // Accept visual roles directly in the options - // as Role: - this._visualRoleList.forEach(function(visualRole){ - var name = visualRole.name; - var roleSpec = options[name + 'Role']; - if(roleSpec !== undefined){ - if(!roleOptions){ - roleOptions = options.visualRoles = {}; - } - - if(roleOptions[name] === undefined){ - roleOptions[name] = roleSpec; - } - } - }); - - var dimsBoundToSingleRole; - if(roleOptions){ - dimsBoundToSingleRole = {}; - - var rolesWithOptions = - def - .query(def.keys(roleOptions)) - .select(function(name){ - return this._visualRoles[name] || - def.fail.operationInvalid("Role '{0}' is not supported by the chart type.", [name]); - }, this) - .array(); - - rolesWithOptions.sort(function(a, b){ return a.index - b.index; }); - - /* Process options.visualRoles */ - rolesWithOptions.forEach(function(visualRole){ - var name = visualRole.name; - var roleSpec = roleOptions[name]; - - // Process the visual role specification - // * a string with the grouping dimensions, or - // * {dimensions: "product", isReversed:true, from: "series" } - var groupingSpec, sourceRoleName; - if(def.object.is(roleSpec)){ - if(def.nullyTo(roleSpec.isReversed, false)){ - visualRole.setIsReversed(true); - } - - sourceRoleName = roleSpec.from; - if(sourceRoleName && (sourceRoleName !== name)){ - var sourceRole = this._visualRoles[sourceRoleName] || - def.fail.operationInvalid("Source role '{0}' is not supported by the chart type.", [sourceRoleName]); - - visualRole.setSourceRole(sourceRole); - sourcedRoles.push(visualRole); - } else { - groupingSpec = roleSpec.dimensions; - } - } else { - // Assumed to be a string (or null, undefined) - groupingSpec = roleSpec; - } - - // !groupingSpec (null or "") results in a null grouping being preBound - // A pre bound null grouping is later discarded in the post bind, - // but, in between, prevents translators from - // reading to dimensions that would bind into those roles... - if(groupingSpec !== undefined){ - var grouping = pvc.data.GroupingSpec.parse(groupingSpec); - - visualRole.preBind(grouping); - - /* Collect dimension names bound to a *single* role */ - grouping.dimensions().each(function(groupDimSpec){ - if(def.hasOwn(dimsBoundToSingleRole, groupDimSpec.name)){ - // two roles => no defaults at all - delete dimsBoundToSingleRole[groupDimSpec.name]; - } else { - dimsBoundToSingleRole[groupDimSpec.name] = visualRole; - } - }); - } - }, this); - - } - - this._sourcedRoles = sourcedRoles; - this._dimsBoundToSingleRole = dimsBoundToSingleRole; - }, - - _bindVisualRolesPreII: function(){ - /* Provide defaults to dimensions bound to a single role - * by using the role's requirements - */ - var dimsBoundToSingleRole = this._dimsBoundToSingleRole; - if(dimsBoundToSingleRole){ - delete this._dimsBoundToSingleRole; // free memory - - def.eachOwn( - dimsBoundToSingleRole, - this._setRoleBoundDimensionDefaults, - this); - } - - var sourcedRoles = this._sourcedRoles; - delete this._sourcedRoles; // free memory - - /* Apply defaultSourceRole to roles not pre-bound */ - def - .query(this._visualRoleList) - .where(function(role){ return role.defaultSourceRoleName && !role.sourceRole && !role.isPreBound(); }) - .each (function(role){ - var sourceRole = this._visualRoles[role.defaultSourceRoleName]; - if(sourceRole){ - role.setSourceRole(sourceRole); - sourcedRoles.push(role); - } - }, this) - ; - - /* Pre-bind sourced roles whose source role is itself pre-bound */ - // Only if the role has no default dimension, cause otherwise, - // it would prevent binding to it, if it comes to exist. - // In those cases, sourcing only effectively happens in the post phase. - sourcedRoles.forEach(function(role){ - var sourceRole = role.sourceRole; - if(sourceRole.isReversed){ - role.setIsReversed(!role.isReversed); - } - - if(!role.defaultDimensionName && sourceRole.isPreBound()){ - role.preBind(sourceRole.preBoundGrouping()); - } - }); - }, - - _setRoleBoundDimensionDefaults: function(role, dimName){ - //var splitId = pvc.splitIndexedId(dimName); - - this._complexTypeProj - .setDimDefaults(dimName, role.dimensionDefaults) - ; -// .setDimDefaults(dimName, { -// label: pvc.buildIndexedId(role.label, splitId[1]) -// }); - }, - - _bindVisualRolesPostI: function(){ - - var complexTypeProj = this._complexTypeProj; - - // Dimension names to roles bound to it - var boundDimTypes = {}; - - var unboundSourcedRoles = []; - - def - .query(this._visualRoleList) - .where(function(role) { return role.isPreBound(); }) - .each (markPreBoundRoleDims, this); - - /* (Try to) Automatically bind **unbound** roles: - * -> to their default dimensions, if they exist and are not yet bound to - * -> if the default dimension does not exist and the - * role allows auto dimension creation, - * creates 1 *hidden* dimension (that will receive only null data) - * - * Validates role required'ness. - */ - def - .query(this._visualRoleList) - .where(function(role) { return !role.isPreBound(); }) - .each (autoBindUnboundRole, this); - - /* Sourced roles that could not be normally bound - * are now finally sourced - */ - unboundSourcedRoles.forEach(tryPreBindSourcedRole, this); - - /* Apply defaults to single-bound-to dimensions - * TODO: this is being repeated for !pre-bound! dimensions - */ - def - .query(def.ownKeys(boundDimTypes)) - .where(function(dimName) { return boundDimTypes[dimName].length === 1; }) - .each (function(dimName){ - var singleRole = boundDimTypes[dimName][0]; - this._setRoleBoundDimensionDefaults(singleRole, dimName); - }, this); - - // ---------------- - - function markDimBoundTo(dimName, role){ - def.array.lazy(boundDimTypes, dimName).push(role); - } - - function dimIsDefined(dimName){ - return complexTypeProj.hasDim(dimName); - } - - function preBindRoleTo(role, dimNames){ - if(def.array.is(dimNames)){ - dimNames.forEach(function(dimName){ - markDimBoundTo(dimName, role); - }); - } else { - markDimBoundTo(dimNames, role); - } - - role.setSourceRole(null); // if any - role.preBind(pvc.data.GroupingSpec.parse(dimNames)); - } - - function preBindRoleToGroupDims(role, groupDimNames){ - if(groupDimNames.length){ - if(role.requireSingleDimension){ - preBindRoleTo(role, groupDimNames[0]); - } else { - preBindRoleTo(role, groupDimNames); - } - } - } - - function preBindRoleToNewDim(role, dimName){ - /* Create a hidden dimension and bind the role and the dimension */ - complexTypeProj.setDim(dimName, {isHidden: true}); - - preBindRoleTo(role, dimName); - } - - function roleIsUnbound(role){ - if(role.isRequired) { - throw def.error.operationInvalid("Chart type requires unassigned role '{0}'.", [role.name]); - } - - // Unbind role from any previous binding - role.bind(null); - role.setSourceRole(null); // if any - } - - function markPreBoundRoleDims(role){ - role.preBoundGrouping() - .dimensionNames() - .forEach(markDimBoundTo); - } - - function autoBindUnboundRole(role){ - var name = role.name; - - // !role.isPreBound() - - /* Try to bind automatically, to defaultDimensionName */ - var dimName = role.defaultDimensionName; - if(!dimName) { - if(role.sourceRole){ - unboundSourcedRoles.push(role); - } else { - roleIsUnbound(role); - } - return; - } - - /* An asterisk at the end of the name indicates - * that any dimension of that group is allowed. - * If the role allows multiple dimensions, - * then the meaning is greedy - use them all. - * Otherwise, use only one. - * - * "product*" - */ - var match = dimName.match(/^(.*?)(\*)?$/) || - def.fail.argumentInvalid('defaultDimensionName'); - - var defaultName = match[1]; - var greedy = /*!!*/match[2]; - if(greedy) { - // TODO: does not respect any index explicitly specified - // before the *. Could mean >=... - var groupDimNames = complexTypeProj.groupDimensionsNames(defaultName); - if(groupDimNames){ - // Default dimension(s) is defined - preBindRoleToGroupDims(role, groupDimNames); - return; - } - // Follow to auto create dimension - - } else if(dimIsDefined(defaultName)){ // defaultName === dimName - preBindRoleTo(role, defaultName); - return; - } - - if(role.autoCreateDimension){ - preBindRoleToNewDim(role, defaultName); - return; - } - - if(role.sourceRole){ - unboundSourcedRoles.push(role); - } else { - roleIsUnbound(role); - } - } - - function tryPreBindSourcedRole(role){ - var sourceRole = role.sourceRole; - if(sourceRole.isPreBound()){ - role.preBind(sourceRole.preBoundGrouping()); - } else { - roleIsUnbound(role); - } - } - }, - - _bindVisualRolesPostII: function(complexType){ - - def - .query(this._visualRoleList) - .where(function(role) { return role.isPreBound(); }) - .each (commitRolePreBinding, this); - - function commitRolePreBinding(role){ - // Commits and validates the grouping specification. - // Null groupings are discarded. - // Sourced roles that were also pre-bound are here normally bound. - role.postBind(complexType); - } - }, - - _logVisualRoles: function(){ - var out = ["VISUAL ROLES MAP SUMMARY", pvc.logSeparator, " VisualRole <-- Dimensions", pvc.logSeparator]; - - def.eachOwn(this._visualRoles, function(role, name){ - out.push(" " + name + def.array.create(18 - name.length, " ").join("") + - (role.grouping ? (" <-- " + role.grouping) : '')); - }); - - this._log(out.join("\n")); - }, - - /** - * Obtains a roles array or a specific role, given its name. - * - * @param {string} roleName The role name. - * @param {object} keyArgs Keyword arguments. - * @param {boolean} assertExists Indicates if an error should be thrown if the specified role name is undefined. - * - * @type pvc.data.VisualRole[]|pvc.data.VisualRole - */ - visualRoles: function(roleName, keyArgs){ - if(roleName == null) { - return def.own(this._visualRoles); - } - - var role = def.getOwn(this._visualRoles, roleName) || null; - if(!role && def.get(keyArgs, 'assertExists', true)) { - throw def.error.argumentInvalid('roleName', "Undefined role name '{0}'.", [roleName]); - } - - return role; - }, - - measureVisualRoles: function(){ - return this._measureVisualRoles; - }, - - measureDimensionsNames: function(){ - return def.query(this._measureVisualRoles) - .select(function(visualRole){ return visualRole.firstDimensionName(); }) - .where(def.notNully) - .array(); - }, - - /** - * Indicates if a role is assigned, given its name. - * - * @param {string} roleName The role name. - * @type boolean - */ - _isRoleAssigned: function(roleName){ - return !!this._visualRoles[roleName].grouping; - }, - - _getDataPartDimName: function(){ - var role = this._dataPartRole; - if(role){ - if(role.isBound()){ - return role.firstDimensionName(); - } - - var preGrouping = role.preBoundGrouping(); - if(preGrouping) { - return preGrouping.firstDimensionName(); - } - - return role.defaultDimensionName; - } - } -}); - diff --git a/pacotes/ccc2/pvc/pvcBasePanel.js b/pacotes/ccc2/pvc/pvcBasePanel.js deleted file mode 100755 index 8446cd2..0000000 --- a/pacotes/ccc2/pvc/pvcBasePanel.js +++ /dev/null @@ -1,2263 +0,0 @@ - -/** - * Base panel. - * A lot of them will exist here, with some common properties. - * Each class that extends pvc.base will be - * responsible to know how to use it. - */ -def -.type('pvc.BasePanel', pvc.Abstract) -.init(function(chart, parent, options) { - - this.chart = chart; // must be set before base() because of log init - - this.base(); - - this.axes = {}; - - if(options){ - if(options.scenes){ - this._sceneTypeExtensions = options.scenes; - delete options.scenes; - } - - var axes = options.axes; - if(axes){ - def.copy(this.axes, axes); - delete options.axes; - } - } - - // TODO: Danger... - $.extend(this, options); - - this.chart = chart; - - if(!this.axes.color){ - this.axes.color = chart.axes.color; - } - - this.position = { - /* - top: 0, - right: 0, - bottom: 0, - left: 0 - */ - }; - - var margins = options && options.margins; - if(!parent && margins === undefined){ - // FIXME: Give a default margin on the root panel - // because otherwise borders of panels may be clipped.. - // Even now that the box model supports borders, - // the "plot" panel still gets drawn outside - // cause it is drawn over? See the box plot... - // The rubber band also should take its border into account - // to not be drawn off... - margins = 3; - } - - this.margins = new pvc.Sides(margins); - this.paddings = new pvc.Sides(options && options.paddings); - this.size = new pvc.Size (options && options.size ); - this.sizeMax = new pvc.Size (options && options.sizeMax ); - - if(!parent) { - this.parent = null; - this.root = this; - this.topRoot = this; - this.isRoot = true; - this.isTopRoot = true; - this.data = this.chart.data; - - } else { - this.parent = parent; - this.isTopRoot = false; - this.isRoot = (parent.chart !== chart); - this.root = this.isRoot ? this : parent.root; - this.topRoot = parent.topRoot; - this.data = parent.data; // TODO - - if(this.isRoot) { - this.position.left = chart.left; - this.position.top = chart.top; - } - - parent._addChild(this); - } - - /* Root panels do not need layout */ - if(this.isRoot) { - this.anchor = null; - this.align = null; - this.alignTo = null; - this.offset = null; - } else { - this.align = pvc.parseAlign(this.anchor, this.align); - - // * a string with a named alignTo value - // * a number - // * a PercentValue object - var alignTo = this.alignTo; - var side = this.anchor; - if(alignTo != null && alignTo !== '' && (side === 'left' || side === 'right')){ - if(alignTo !== 'page-middle'){ - if(!isNaN(+alignTo.charAt(0))){ - alignTo = pvc.PercentValue.parse(alignTo); // percent or number - } else { - alignTo = pvc.parseAlign(side, alignTo); - } - } - } else { - alignTo = this.align; - } - - this.alignTo = alignTo; - - this.offset = new pvc.Offset(this.offset); - } - - if(this.borderWidth == null){ - var borderWidth; - var extensionId = this._getExtensionId(); - if(extensionId){ - var strokeStyle = this._getExtension(extensionId, 'strokeStyle'); - if(strokeStyle != null){ - borderWidth = +this._getConstantExtension(extensionId, 'lineWidth'); - if(isNaN(borderWidth) || !isFinite(borderWidth)){ - borderWidth = null; - } - } - } - - this.borderWidth = borderWidth == null ? 0 : 1.5; - } -}) -.add({ - chart: null, - parent: null, - _children: null, - type: pv.Panel, // default one - - _extensionPrefix: '', - - /** - * Total height of the panel in pixels. - * Includes vertical paddings and margins. - * @type number - */ - height: null, - - /** - * Total width of the panel in pixels. - * Includes horizontal paddings and margins. - * @type number - */ - width: null, - - /** - * The static effective border width of the panel. - * - * If a constant extension point exists, - * its value is used to initialize this property. - * - * If an extension point exists for the strokeStyle property, - * and its value is not null, - * the width, taken from the extension point, or defaulted, is considered. - * Otherwise, the effective width is 0. - * - * The default active value is 1.5. - * - * @type number - */ - borderWidth: null, - - anchor: "top", - - pvPanel: null, // padding/client pv panel (within border box, separated by paddings) - - margins: null, - paddings: null, - - isRoot: false, - isTopRoot: false, - root: null, - topRoot: null, - - _layoutInfo: null, // once per layout info - - _signs: null, - - /** - * The data that the panel uses to obtain "data". - * @type pvc.data.Data - */ - data: null, - - dataPartValue: null, - - /** - * Indicates if the top root panel is rendering with animation - * and, if so, the current phase of animation. - * - *

This property can assume the following values:

- *
    - *
  • 0 - Not rendering with animation (may even not be rendering at all).
  • - *
  • 1 - Rendering the animation's start point,
  • - *
  • 2 - Rendering the animation's end point.
  • - *
- * - * @see #animate - * @see #isAnimatingStart - * - * @type number - */ - _isAnimating: 0, - - _isRubberBandSelecting: false, - - /** - * Shared state between {@link _handleClick} and {@link #_handleDoubleClick}. - */ - _ignoreClicks: 0, - - /** - * Indicates the name of the role that should be used whenever a V1 dimension value is required. - * Only the first dimension of the specified role is considered. - *

- * In a derived class use {@link Object.create} to override this object for only certain - * v1 dimensions. - *

- * @ type string - */ - _v1DimRoleName: { - 'series': 'series', - 'category': 'category', - 'value': 'value' - }, - - _sceneTypeExtensions: null, - - clickAction: null, - doubleClickAction: null, - - compatVersion: function(options){ - return this.chart.compatVersion(options); - }, - - _createLogInstanceId: function(){ - return "" + - this.constructor + this.chart._createLogChildSuffix(); - }, - - defaultVisibleBulletGroupScene: function(){ - // Return legendBulletGroupScene, - // from the first data cell of same dataPartValue and - // having one legendBulletGroupScene. - var colorAxis = this.axes.color; - if(colorAxis && colorAxis.option('LegendVisible')){ - var dataPartValue = this.dataPartValue; - return def - .query(colorAxis.dataCells) - .where(function(dataCell){ return dataCell.dataPartValue === dataPartValue; }) - .select(function(dataCell){ return dataCell.legendBulletGroupScene; }) - .first(def.truthy) - ; - } - - return null; - }, - - _getLegendBulletRootScene: function(){ - return this.chart._getLegendBulletRootScene(); - }, - - /** - * Adds a panel as child. - */ - _addChild: function(child){ - // - /*jshint expr:true */ - child.parent === this || def.assert("Child has a != parent."); - // - - (this._children || (this._children = [])).push(child); - }, - - _addSign: function(sign){ - (this._signs || (this._signs = [])).push(sign); - }, - - visibleData: function(){ - return this.chart.visibleData(this.dataPartValue); - }, - - /* LAYOUT PHASE */ - - /** - * Calculates and sets its size, - * taking into account a specified total size. - * - * @param {pvc.Size} [availableSize] The total size available for the panel. - *

- * On root panels this argument is not specified, - * and the panels' current {@link #width} and {@link #height} are used as default. - *

- * @param {object} [keyArgs] Keyword arguments. - * @param {boolean} [keyArgs.force=false] Indicates that the layout should be - * performed even if it has already been done. - * @param {pvc.Size} [keyArgs.referenceSize] The size that should be used for - * percentage size calculation. - * This will typically be the client size of the parent. - * @param {pvc.Sides} [keyArgs.paddings] The paddings that should be used for - * the layout. Default to the panel's paddings {@link #paddings}. - * @param {pvc.Sides} [keyArgs.margins] The margins that should be used for - * the layout. Default to the panel's margins {@link #margins}. - * @param {boolean} [keyArgs.canChange=true] Whether this is a last time layout. - */ - layout: function(availableSize, keyArgs){ - if(!this._layoutInfo || def.get(keyArgs, 'force', false)) { - - var referenceSize = def.get(keyArgs, 'referenceSize'); - if(!referenceSize && availableSize){ - referenceSize = def.copyOwn(availableSize); - } - - // Does this panel have a **desired** fixed size specified? - - // * size may have no specified components - // * referenceSize may be null - var desiredSize = this.size.resolve(referenceSize); - var sizeMax = this.sizeMax.resolve(referenceSize); - - if(!availableSize) { - if(desiredSize.width == null || desiredSize.height == null){ - throw def.error.operationInvalid("Panel layout without width or height set."); - } - - availableSize = def.copyOwn(desiredSize); - } - - if(!referenceSize && availableSize){ - referenceSize = def.copyOwn(availableSize); - } - - // Apply max size to available size - if(sizeMax.width != null && availableSize.width > sizeMax.width){ - availableSize.width = sizeMax.width; - } - - if(sizeMax.height != null && availableSize.height > sizeMax.height){ - availableSize.height = sizeMax.height; - } - - var halfBorder = this.borderWidth / 2; - var realMargins = (def.get(keyArgs, 'margins' ) || this.margins ).resolve(referenceSize); - var realPaddings = (def.get(keyArgs, 'paddings') || this.paddings).resolve(referenceSize); - - var margins = pvc.Sides.inflate(realMargins, halfBorder); - var paddings = pvc.Sides.inflate(realPaddings, halfBorder); - - var spaceWidth = margins.width + paddings.width; - var spaceHeight = margins.height + paddings.height; - - var availableClientSize = new pvc.Size( - Math.max(availableSize.width - spaceWidth, 0), - Math.max(availableSize.height - spaceHeight, 0) - ); - - var desiredClientSize = def.copyOwn(desiredSize); - if(desiredClientSize.width != null){ - desiredClientSize.width = Math.max(desiredClientSize.width - spaceWidth, 0); - } - - if(desiredClientSize.height != null){ - desiredClientSize.height = Math.max(desiredClientSize.height - spaceHeight, 0); - } - - var prevLayoutInfo = this._layoutInfo || null; - var canChange = def.get(keyArgs, 'canChange', true); - - var layoutInfo = - this._layoutInfo = { - canChange: canChange, - referenceSize: referenceSize, - - realMargins: realMargins, - realPaddings: realPaddings, - - borderWidth: this.borderWidth, - - margins: margins, - paddings: paddings, - - desiredClientSize: desiredClientSize, - clientSize: availableClientSize, - - pageClientSize: prevLayoutInfo ? prevLayoutInfo.pageClientSize : availableClientSize.clone(), - previous: prevLayoutInfo - }; - - if(prevLayoutInfo){ - // Free old memory - delete prevLayoutInfo.previous; - delete prevLayoutInfo.pageClientSize; - } - - var clientSize = this._calcLayout(layoutInfo); - - var size; - if(!clientSize){ - size = availableSize; // use all available size - clientSize = availableClientSize; - } else { - layoutInfo.clientSize = clientSize; - size = { - width: clientSize.width + spaceWidth, - height: clientSize.height + spaceHeight - }; - } - - this.isVisible = (clientSize.width > 0 && clientSize.height > 0); - - delete layoutInfo.desiredClientSize; - - this.width = size.width; - this.height = size.height; - - if(!canChange && prevLayoutInfo){ - delete layoutInfo.previous; - } - - if(pvc.debug >= 5){ - this._log("Size = " + pvc.stringify(size)); - this._log("Margins = " + pvc.stringify(layoutInfo.margins)); - this._log("Paddings = " + pvc.stringify(layoutInfo.paddings)); - this._log("ClientSize = " + pvc.stringify(layoutInfo.clientSize)); - } - - this._onLaidOut(); - } - }, - - _onLaidOut: function(){ - if(this.isRoot){ - this.chart._onLaidOut(); - } - }, - - /** - * Override to calculate panel client size. - *

- * The default implementation performs a dock layout {@link #layout} on child panels - * and uses all of the available size. - *

- * - * @param {object} layoutInfo An object that is supplied with layout information - * and on which to export custom layout information. - *

- * This object is later supplied to the method {@link #_createCore}, - * and can thus be used to store any layout by-product - * relevant for the creation of the protovis marks and - * that should be cleared whenever a layout becomes invalid. - *

- *

- * The object is supplied with the following properties: - *

- *
    - *
  • referenceSize - size that should be used for percentage size calculation. - * This will typically be the client size of the parent. - *
  • - *
  • margins - the resolved margins object. All components are present, possibly with the value 0.
  • - *
  • paddings - the resolved paddings object. All components are present, possibly with the value 0.
  • - *
  • desiredClientSize - the desired fixed client size. Do ignore a null width or height property value.
  • - *
  • clientSize - the available client size, already limited by a maximum size if specified.
  • - *
- *

- * Do not modify the contents of the objects of - * any of the supplied properties. - *

- * @virtual - */ - _calcLayout: function(layoutInfo){ - var clientSize; - var me = this; - - // These are used in layoutCycle - var margins, remSize, useLog; - - if(me._children) { - var aolMap = pvc.BasePanel.orthogonalLength; - var aoMap = pvc.BasePanel.relativeAnchor; - var altMap = pvc.BasePanel.leftTopAnchor; - var aofMap = pvc.Offset.namesSidesToOffset; - - // Classify children - - var fillChildren = []; - var sideChildren = []; - - me._children.forEach(function(child) { - var a = child.anchor; - if(a){ // requires layout - if(a === 'fill') { - fillChildren.push(child); - } else { - /*jshint expr:true */ - def.hasOwn(aoMap, a) || def.fail.operationInvalid("Unknown anchor value '{0}'", [a]); - - sideChildren.push(child); - } - } - }); - - useLog = pvc.debug >= 5; - - // When expanded (see checkChildLayout) - // a re-layout is performed. - clientSize = def.copyOwn(layoutInfo.clientSize); - var childKeyArgs = { - force: true, - referenceSize: clientSize - }; - - if(useLog){ me._group("CCC DOCK LAYOUT clientSize = " + pvc.stringify(clientSize)); } - try{ - doMaxTimes(5, layoutCycle, me); - } finally { - if(useLog){ me._groupEnd(); } - } - } - - /* Return possibly changed clientSize */ - return clientSize; - - // -------------------- - function doMaxTimes(maxTimes, fun, ctx){ - var index = 0; - while(maxTimes--){ - // remTimes = maxTimes - if(fun.call(ctx, maxTimes, index) === false){ - return true; - } - index++; - } - - return false; - } - - function layoutCycle(remTimes, iteration){ - if(useLog){ me._group("LayoutCycle #" + (iteration + 1) + " (remaining: " + remTimes + ")"); } - try{ - var canResize = (remTimes > 0); - - // Reset margins and remSize - // ** Instances we can mutate - margins = new pvc.Sides(0); - remSize = def.copyOwn(clientSize); - - // Lay out SIDE child panels - var child; - var index = 0; - var count = sideChildren.length; - while(index < count){ - child = sideChildren[index]; - if(useLog){ me._group("SIDE Child #" + (index + 1) + " at " + child.anchor); } - try{ - if(layoutChild.call(this, child, canResize)){ - return true; // resized => break - } - } finally { - if(useLog){ me._groupEnd(); } - } - index++; - } - - // Lay out FILL child panels - index = 0; - count = fillChildren.length; - while(index < count){ - child = fillChildren[index]; - if(useLog){ me._group("FILL Child #" + (index + 1)); } - try{ - if(layoutChild.call(this, child, canResize)){ - return true; // resized => break - } - } finally { - if(useLog){ me._groupEnd(); } - } - index++; - } - - return false; // !resized - } finally { - if(useLog){ me._groupEnd(); } - } - } - - function layoutChild(child, canResize) { - var resized = false; - var paddings; - - childKeyArgs.canChange = canResize; - - doMaxTimes(3, function(remTimes, iteration){ - if(useLog){ me._group("Attempt #" + (iteration + 1)); } - try{ - - childKeyArgs.paddings = paddings; - childKeyArgs.canChange = remTimes > 0; - - child.layout(new pvc.Size(remSize), childKeyArgs); - if(child.isVisible){ - resized = checkChildResize.call(this, child, canResize); - if(resized){ - return false; // stop - } - - var requestPaddings = child._layoutInfo.requestPaddings; - if(checkPaddingsChanged(paddings, requestPaddings)){ - paddings = requestPaddings; - - // Child wants to repeat its layout with != paddings - if(remTimes > 0){ - paddings = new pvc.Sides(paddings); - if(useLog){ this._log("Child requested paddings change: " + pvc.stringify(paddings)); } - return true; // again - } - - if(pvc.debug >= 2){ - this._warn("Child requests paddings change but iterations limit has been reached."); - } - // ignore overflow - } - - // -------- - - positionChild.call(this, child); - - if(child.anchor !== 'fill'){ - updateSide.call(this, child); - } - } - - return false; // stop - } finally { - if(useLog){ me._groupEnd(); } - } - }, this); - - return resized; - } - - function checkPaddingsChanged(paddings, newPaddings){ - if(!newPaddings){ - return false; - } - - // true if stopped, false otherwise - return def.query(pvc.Sides.names).each(function(side){ - var curPad = (paddings && paddings[side]) || 0; - var newPad = (newPaddings && newPaddings[side]) || 0; - if(Math.abs(newPad - curPad) >= 0.1){ - // Stop iteration - return false; - } - }); - } - - function checkChildResize(child, canResize){ - var resized = false; - var addWidth = child.width - remSize.width; - if(addWidth > 0){ - if(pvc.debug >= 3){ - this._log("Child added width = " + addWidth); - } - - if(!canResize){ - if(pvc.debug >= 2){ - this._warn("Child wanted more width, but layout iterations limit has been reached."); - } - } else { - resized = true; - - remSize .width += addWidth; - clientSize.width += addWidth; - } - } - - var addHeight = child.height - remSize.height; - if(addHeight > 0){ - if(pvc.debug >= 3){ - this._log("Child added height =" + addHeight); - } - - if(!canResize){ - if(pvc.debug >= 2){ - this._warn("Child wanted more height, but layout iterations limit has been reached."); - } - } else { - resized = true; - - remSize .height += addHeight; - clientSize.height += addHeight; - } - } - - return resized; - } - - function positionChild(child) { - var side = child.anchor; - var align = child.align; - var alignTo = child.alignTo; - var sidePos; - if(side === 'fill'){ - side = 'left'; - sidePos = margins.left + remSize.width / 2 - (child.width / 2); - align = alignTo = 'middle'; - } else { - sidePos = margins[side]; - } - - var sideo, sideOPosChildOffset; - switch(align){ - case 'top': - case 'bottom': - case 'left': - case 'right': - sideo = align; - sideOPosChildOffset = 0; - break; - - case 'center': - case 'middle': - // 'left', 'right' -> 'top' - // else -> 'left' - sideo = altMap[aoMap[side]]; - - // left -> width; top -> height - sideOPosChildOffset = - child[aolMap[sideo]] / 2; - break; - } - - - var sideOPosParentOffset; - var sideOTo; - switch(alignTo){ - case 'top': - case 'bottom': - case 'left': - case 'right': - sideOTo = alignTo; - sideOPosParentOffset = (sideOTo !== sideo) ? remSize[aolMap[sideo]] : 0; - break; - - case 'center': - case 'middle': - sideOTo = altMap[aoMap[side]]; - - sideOPosParentOffset = remSize[aolMap[sideo]] / 2; - break; - - case 'page-center': - case 'page-middle': - sideOTo = altMap[aoMap[side]]; - - var lenProp = aolMap[sideo]; - var pageLen = Math.min(remSize[lenProp], layoutInfo.pageClientSize[lenProp]); - sideOPosParentOffset = pageLen / 2; - break; - } - - var sideOPos = margins[sideOTo] + sideOPosParentOffset + sideOPosChildOffset; - - var resolvedOffset = child.offset.resolve(remSize); - if(resolvedOffset){ - sidePos += resolvedOffset[aofMap[side ]] || 0; - sideOPos += resolvedOffset[aofMap[sideo]] || 0; - } - - if(child.keepInBounds){ - if(sidePos < 0){ - sidePos = 0; - } - - if(sideOPos < 0){ - sideOPos = 0; - } - } - - child.setPosition( - def.set({}, - side, sidePos, - sideo, sideOPos)); - } - - // Decreases available size and increases margins - function updateSide(child) { - var side = child.anchor; - var sideol = aolMap[side]; - var olen = child[sideol]; - - margins[side] += olen; - remSize[sideol] -= olen; - } - }, - - invalidateLayout: function(){ - this._layoutInfo = null; - - if(this._children) { - this._children.forEach(function(child){ - child.invalidateLayout(); - }); - } - }, - - /** - * CREATION PHASE - * - * Where the protovis main panel, and any other marks, are created. - * - * If the layout has not been performed it is so now. - */ - _create: function(force) { - if(!this.pvPanel || force) { - - this.pvPanel = null; - - delete this._signs; - - /* Layout */ - this.layout(); - - if(!this.isVisible){ - return; - } - - if(this.isRoot){ - this._creating(); - } - - var margins = this._layoutInfo.margins; - var paddings = this._layoutInfo.paddings; - - /* Protovis Panel */ - if(this.isTopRoot) { - this.pvRootPanel = - this.pvPanel = new pv.Panel().canvas(this.chart.options.canvas); - - if(margins.width > 0 || margins.height > 0){ - this.pvPanel - .width (this.width ) - .height(this.height); - - // As there is no parent panel, - // the margins cannot be accomplished by positioning - // on the parent panel and sizing. - // We thus create another panel to be a child of pvPanel - - this.pvPanel = this.pvPanel.add(pv.Panel); - } - } else { - this.pvPanel = this.parent.pvPanel.add(this.type); - } - - var pvBorderPanel = this.pvPanel; - - // Set panel size - var width = this.width - margins.width; - var height = this.height - margins.height; - pvBorderPanel - .width (width) - .height(height); - - if(pvc.debug >= 15 && (margins.width > 0 || margins.height > 0)){ - // Outer Box - (this.isTopRoot ? this.pvRootPanel : this.parent.pvPanel) - .add(this.type) - .width (this.width) - .height(this.height) - .left (this.position.left != null ? this.position.left : null) - .right (this.position.right != null ? this.position.right : null) - .top (this.position.top != null ? this.position.top : null) - .bottom(this.position.bottom != null ? this.position.bottom : null) - .strokeStyle('orange') - .lineWidth(1) - .strokeDasharray('- .') - ; - } - - // Set panel positions - var hasPositions = {}; - def.eachOwn(this.position, function(v, side){ - pvBorderPanel[side](v + margins[side]); - hasPositions[this.anchorLength(side)] = true; - }, this); - - if(!hasPositions.width){ - if(margins.left > 0){ - pvBorderPanel.left(margins.left); - } - if(margins.right > 0){ - pvBorderPanel.right(margins.right); - } - } - - if(!hasPositions.height){ - if(margins.top > 0){ - pvBorderPanel.top(margins.top); - } - if(margins.bottom > 0){ - pvBorderPanel.bottom(margins.bottom); - } - } - - // Check padding - if(paddings.width > 0 || paddings.height > 0){ - // We create separate border (outer) and inner (padding) panels - this.pvPanel = pvBorderPanel.add(pv.Panel) - .width (width - paddings.width ) - .height(height - paddings.height) - .left(paddings.left) - .top (paddings.top ); - } - - pvBorderPanel.borderPanel = pvBorderPanel; - pvBorderPanel.paddingPanel = this.pvPanel; - - this.pvPanel.paddingPanel = this.pvPanel; - this.pvPanel.borderPanel = pvBorderPanel; - - if(pvc.debug >= 15){ - // Client Box - this.pvPanel - .strokeStyle('lightgreen') - .lineWidth(1) - .strokeDasharray('- '); - - if(this.pvPanel !== pvBorderPanel){ - // Border Box - pvBorderPanel - .strokeStyle('blue') - .lineWidth(1) - .strokeDasharray('. '); - } - } - - var extensionId = this._getExtensionId(); -// if(extensionId != null){ // '' is allowed cause this is relative to #_getExtensionPrefix - // Wrap the panel that is extended with a Panel sign - new pvc.visual.Panel(this, null, { - panel: pvBorderPanel, - extensionId: extensionId - }); -// } - - /* Protovis marks that are pvc Panel specific, - * and/or create child panels. - */ - this._createCore(this._layoutInfo); - - /* RubberBand */ - if (this.isTopRoot && pv.renderer() !== 'batik' && this.chart._canSelectWithRubberband()){ - this._initRubberBand(); - } - - /* Extensions */ - this.applyExtensions(); - } - }, - - _creating: function(){ - if(this._children) { - this._children.forEach(function(child){ - child._creating(); - }); - } - }, - - /** - * Override to create specific protovis components for a given panel. - * - * The default implementation calls {@link #_create} on each child panel. - * - * @param {object} layoutInfo The object with layout information - * "exported" by {@link #_calcLayout}. - * - * @virtual - */ - _createCore: function(/*layoutInfo*/){ - if(this._children) { - this._children.forEach(function(child){ - child._create(); - }); - } - }, - - /** - * RENDER PHASE - * - * Where protovis components are rendered. - * - * If the creation phase has not been performed it is so now. - */ - - /** - * Renders the top root panel. - *

- * The render is always performed from the top root panel, - * independently of the panel on which the method is called. - *

- * - * @param {object} [keyArgs] Keyword arguments. - * @param {boolean} [keyArgs.bypassAnimation=false] Indicates that animation should not be performed. - * @param {boolean} [keyArgs.recreate=false] Indicates that the panel and its descendants should be recreated. - */ - render: function(keyArgs){ - - if(!this.isTopRoot) { - return this.topRoot.render(keyArgs); - } - - this._create(def.get(keyArgs, 'recreate', false)); - - if(!this.isVisible){ - return; - } - - this._onRender(); - - var options = this.chart.options; - var pvPanel = this.pvRootPanel; - - var animate = this.chart._animatable && options.animate; - this._isAnimating = animate && !def.get(keyArgs, 'bypassAnimation', false) ? 1 : 0; - try { - // When animating, renders the animation's 'start' point - pvPanel.render(); - - // Transition to the animation's 'end' point - if (this._isAnimating) { - this._isAnimating = 2; - - var me = this; - pvPanel - .transition() - .duration(2000) - .ease("cubic-in-out") - .start(function(){ - me._isAnimating = 0; - me._onRenderEnd(true); - }); - } else { - this._onRenderEnd(false); - } - } finally { - this._isAnimating = 0; - } - }, - - _onRender: function(){ - var renderCallback = this.chart.options.renderCallback; - if (renderCallback) { - if(this.compatVersion() <= 1){ - renderCallback.call(this.chart); - } else { - var context = this._getContext(); - renderCallback.call(context, context.scene); - } - } - }, - - /** - * Called when a render has ended. - * When the render performed an animation - * and the 'animated' argument will have the value 'true'. - * - * The default implementation calls each child panel's - * #_onRenderEnd method. - * @virtual - */ - _onRenderEnd: function(animated){ - if(this._children){ - this._children.forEach(function(child){ - child._onRenderEnd(animated); - }); - } - }, - - /** - * The default implementation renders - * the marks returned by #_getSelectableMarks, - * or this.pvPanel if none is returned (and it has no children) - * which is generally in excess of what actually requires - * to be re-rendered. - * The call is then propagated to any child panels. - * - * @virtual - */ - renderInteractive: function(){ - if(this.isVisible){ - var pvMarks = this._getSelectableMarks(); - if(pvMarks && pvMarks.length){ - pvMarks.forEach(function(pvMark){ pvMark.render(); }); - } else if(!this._children) { - this.pvPanel.render(); - return; - } - - if(this._children){ - this._children.forEach(function(child){ - child.renderInteractive(); - }); - } - } - }, - - /** - * Returns an array of marks whose instances are associated to a datum, or null. - * @virtual - */ - _getSelectableMarks: function(){ - return null; - }, - - - /* ANIMATION */ - - animate: function(start, end) { - return (this.topRoot._isAnimating === 1) ? start : end; - }, - - /** - * Indicates if the panel is currently - * rendering the animation start phase. - *

- * Prefer using this function instead of {@link #animate} - * whenever its start or end arguments - * involve a non-trivial calculation. - *

- * - * @type boolean - */ - isAnimatingStart: function() { - return (this.topRoot._isAnimating === 1); - }, - - /** - * Indicates if the panel is currently - * rendering animation. - * - * @type boolean - */ - isAnimating: function() { - return (this.topRoot._isAnimating > 0); - }, - - /* SIZE & POSITION */ - setPosition: function(position){ - for(var side in position){ - if(def.hasOwn(pvc.Sides.namesSet, side)){ - var s = position[side]; - if(s === null) { - delete this.position[side]; - } else { - s = +s; // -> to number - if(!isNaN(s) && isFinite(s)){ - this.position[side] = s; - } - } - } - } - }, - - createAnchoredSize: function(anchorLength, size){ - if (this.isAnchorTopOrBottom()) { - return new pvc.Size(size.width, Math.min(size.height, anchorLength)); - } - return new pvc.Size(Math.min(size.width, anchorLength), size.height); - }, - - /* EXTENSION */ - - /** - * Override to apply specific extensions points. - * @virtual - */ - applyExtensions: function(){ - if (this._signs) { - this._signs.forEach(function(sign){ - sign.applyExtensions(); - }); - } - }, - - /** - * Extends a protovis mark with extension points - * having a given panel-relative component id. - */ - extend: function(mark, id, keyArgs) { - this.chart.extend(mark, this._makeExtensionAbsId(id), keyArgs); - }, - - /** - * Extends a protovis mark with extension points - * having a given absolute component id. - */ - extendAbs: function(mark, absId, keyArgs) { - this.chart.extend(mark, absId, keyArgs); - }, - - _extendSceneType: function(typeKey, type, names){ - var typeExts = def.get(this._sceneTypeExtensions, typeKey); - if(typeExts){ - pvc.extendType(type, typeExts, names); - } - }, - - _absBaseExtId: {abs: 'base'}, - _absSmallBaseExtId: {abs: 'smallBase'}, - - _getExtensionId: function(){ - if (this.isRoot) { - return !this.chart.parent ? this._absBaseExtId : this._absSmallBaseExtId; - } - }, - - _getExtensionPrefix: function(){ - return this._extensionPrefix; - }, - - _makeExtensionAbsId: function(id){ - return pvc.makeExtensionAbsId(id, this._getExtensionPrefix()); - }, - - /** - * Obtains an extension point given its identifier and property. - */ - _getExtension: function(id, prop) { - return this.chart._getExtension(this._makeExtensionAbsId(id), prop); - }, - - _getExtensionAbs: function(absId, prop) { - return this.chart._getExtension(absId, prop); - }, - - _getConstantExtension: function(id, prop) { - return this.chart._getConstantExtension(this._makeExtensionAbsId(id), prop); - }, - - // ----------------------------- - - /** - * Returns the underlying protovis Panel. - * If 'layer' is specified returns - * the protovis panel for the specified layer name. - */ - getPvPanel: function(layer) { - var mainPvPanel = this.pvPanel; - if(!layer){ - return mainPvPanel; - } - - if(!this.parent){ - throw def.error.operationInvalid("Layers are not possible in a root panel."); - } - - if(!mainPvPanel){ - throw def.error.operationInvalid( - "Cannot access layer panels without having created the main panel."); - } - - var pvPanel = null; - if(!this._layers){ - this._layers = {}; - } else { - pvPanel = this._layers[layer]; - } - - if(!pvPanel){ - var pvParentPanel = this.parent.pvPanel; - - pvPanel = pvParentPanel.borderPanel.add(this.type) - .extend(mainPvPanel.borderPanel); - - var pvBorderPanel = pvPanel; - - if(mainPvPanel !== mainPvPanel.borderPanel){ - pvPanel = pvBorderPanel.add(pv.Panel) - .extend(mainPvPanel); - } - - pvBorderPanel.borderPanel = pvBorderPanel; - pvBorderPanel.paddingPanel = pvPanel; - - pvPanel.paddingPanel = pvPanel; - pvPanel.borderPanel = pvBorderPanel; - - this.initLayerPanel(pvPanel, layer); - - this._layers[layer] = pvPanel; - } - - return pvPanel; - }, - - /** - * Initializes a new layer panel. - * @virtual - */ - initLayerPanel: function(/*pvPanel, layer*/){}, - - /* EVENTS & VISUALIZATION CONTEXT */ - _getV1DimName: function(v1Dim){ - var dimNames = this._v1DimName || (this._v1DimNameCache = {}); - var dimName = dimNames[v1Dim]; - if(dimName == null) { - var role = this.chart.visualRoles(this._v1DimRoleName[v1Dim], {assertExists: false}); - dimName = role ? role.firstDimensionName() : ''; - dimNames[v1Dim] = dimName; - } - - return dimName; - }, - - _getV1Datum: function(scene){ - return scene.datum; - }, - - /** - * Creates the visualization context of the panel. - *

- * Override to use a specific visualization context class. - *

- * - * @param {pv.Mark} mark The protovis mark being rendered or targeted by an event. - * @param {object} [event] An event object. - * @type pvc.visual.Context - * @virtual - */ - _createContext: function(mark, ev){ - return new pvc.visual.Context(this, mark, ev); - }, - - /** - * Obtains the visualization context of the panel, - * prepared for a specified mark and event. - * - * Creates a new context when necessary. - * - *

- * Override to perform specific updates. - *

- * - * @param {pv.Mark} mark The protovis mark being rendered or targeted by an event. - * @param {object} [event] An event object. - * @type pvc.visual.Context - * @virtual - */ - _getContext: function(mark, ev){ - var context = this._context; - if(!context || context.isPinned){ - this._context = this._createContext(mark, ev); - } else { - /*global visualContext_update:true */ - visualContext_update.call(context, mark, ev); - } - - return this._context; - }, - - _isTooltipEnabled: function(){ - return !this.isRubberBandSelecting() && !this.isAnimating(); - }, - - _ensurePropEvents: function(pvMark){ - // labels and other marks don't receive events by default - var events = pvMark.propertyValue('events', /*inherit*/ true); - if(!events || events === 'none'){ - pvMark.events('all'); - } - }, - - /* HOVERABLE */ - _addPropHoverable: function(pvMark){ - var panel = this; - - var onEvent; - var offEvent; -// switch(pvMark.type) { -// default: -// case 'dot': -// case 'line': -// case 'area': -// case 'rule': -// onEvent = 'point'; -// offEvent = 'unpoint'; -// panel._requirePointEvent(); -// break; - -// default: - onEvent = 'mouseover'; - offEvent = 'mouseout'; -// break; -// } - - pvMark - .event(onEvent, function(scene){ - if(!panel.isRubberBandSelecting() && !panel.isAnimating()) { - scene.setActive(true); - panel.renderInteractive(); - } - }) - .event(offEvent, function(scene){ - if(!panel.isRubberBandSelecting() && !panel.isAnimating()) { - if(scene.clearActive()) { - /* Something was active */ - panel.renderInteractive(); - } - } - }); - - this._ensurePropEvents(pvMark); - }, - - /* TOOLTIP */ - _addPropTooltip: function(pvMark, keyArgs){ - var chartTipOptions = this.chart._tooltipOptions; - - var tipOptions; - var nowTipOptions = def.get(keyArgs, 'options'); - if(nowTipOptions){ - tipOptions = def.create(chartTipOptions, nowTipOptions); - } else { - tipOptions = Object.create(chartTipOptions); - } - - var buildTooltip = def.get(keyArgs, 'buildTooltip') || - this._getTooltipBuilder(tipOptions); - if(!buildTooltip){ - return; - } - - tipOptions.isEnabled = this._isTooltipEnabled.bind(this); - - var tipsyEvent = def.get(keyArgs, 'tipsyEvent'); - if(!tipsyEvent) { -// switch(pvMark.type) { -// case 'dot': -// case 'line': -// case 'area': -// this._requirePointEvent(); -// tipsyEvent = 'point'; -// tipOptions.usesPoint = true; -// break; - -// default: - tipsyEvent = 'mouseover'; -// } - } - - var isLazy = def.get(keyArgs, 'isLazy', true); - - pvMark.localProperty("tooltip"/*, Function | String*/) - .tooltip(this._createTooltipProp(pvMark, buildTooltip, isLazy)) - .title(function(){ return '';} ) // Prevent browser tooltip - .event(tipsyEvent, pv.Behavior.tipsy(tipOptions)); - - this._ensurePropEvents(pvMark); - }, - - _getTooltipBuilder: function(tipOptions){ - var options = this.chart.options; - var isV1Compat = this.compatVersion() <= 1; - - var tooltipFormat = tipOptions.format; - if(!tooltipFormat) { - if(!isV1Compat){ - return this._buildDataTooltip; - } - - tooltipFormat = options.v1StyleTooltipFormat; - if(!tooltipFormat){ - return; - } - } - - if(isV1Compat){ - return function(context){ - return tooltipFormat.call( - context.panel, - context.getV1Series(), - context.getV1Category(), - context.getV1Value() || '', - context.getV1Datum()); - }; - } - - return function(context){ - return tooltipFormat.call(context, context.scene); - }; - }, - - _createTooltipProp: function(pvMark, buildTooltip, isLazy){ - var myself = this; - if(!isLazy){ - return function(){ - // Capture current context - var context = myself._getContext(pvMark, null); - - // discard intermediate points - if (context.scene.isIntermediate){ - return null; - } - - return buildTooltip.call(myself, context); - }; - } - - return function(){ - // Capture current context - var context = myself._getContext(pvMark, null); - - // discard intermediate points - if (context.scene.isIntermediate){ - return null; - } - - context.pin(); - - var tooltip; - return function() { - if(tooltip == null) { - tooltip = buildTooltip.call(myself, context); - context = null; // release pinned context; - } - - return tooltip; - }; - }; - }, - - _requirePointEvent: function(radius){ - if(!this.isTopRoot) { - return this.topRoot._requirePointEvent(radius); - } - - if(!this._attachedPointEvent){ - - // Fire point and unpoint events - this.pvPanel - .events('all') - .event("mousemove", pv.Behavior.point(radius || 20)); - - this._attachedPointEvent = true; - } - }, - - _buildDataTooltip: function(context){ - - var scene = context.scene; - - // No group and no datum? - if(!scene.datum) { - return ""; - } - - var group = scene.group; - var isMultiDatumGroup = group && group.count() > 1; - - // Single null datum? - var firstDatum = scene.datum; - if(!isMultiDatumGroup && (!firstDatum || firstDatum.isNull)) { - return ""; - } - - var data = this.data; - var visibleKeyArgs = {visible: true}; - - var tooltip = []; - - if(firstDatum.isInterpolated){ - tooltip.push('Interpolation: ' + def.html.escape(firstDatum.interpolation) + '
'); - } else if(firstDatum.isTrend){ - tooltip.push('Trend: ' + def.html.escape(firstDatum.trendType) + '
'); - } - - var complexType = data.type; - - /* TODO: Big HACK to prevent percentages from - * showing up in the Lines of BarLine - */ - var playingPercentMap = context.panel.stacked === false ? - null : - complexType.getPlayingPercentVisualRoleDimensionMap(); - - var percentValueFormat = playingPercentMap ? - this.chart.options.percentValueFormat: - null; - - var commonAtoms = isMultiDatumGroup ? group.atoms : scene.datum.atoms; - var commonAtomsKeys = complexType.sortDimensionNames(def.keys(commonAtoms)); - - function addDim(escapedDimLabel, label){ - tooltip.push('' + escapedDimLabel + ": " + (def.html.escape(label) || " - ") + '
'); - } - - function calcPercent(atom, dimName) { - var pct; - if(group) { - pct = group.dimensions(dimName).percentOverParent(visibleKeyArgs); - } else { - pct = data.dimensions(dimName).percent(atom.value); - } - - return percentValueFormat(pct); - } - - var anyCommonAtom = false; - commonAtomsKeys.forEach(function(dimName){ - var atom = commonAtoms[dimName]; - var dimType = atom.dimension.type; - if(!dimType.isHidden){ - if(!isMultiDatumGroup || atom.value != null) { - anyCommonAtom = true; - - var valueLabel = atom.label; - if(playingPercentMap && playingPercentMap.has(dimName)) { - valueLabel += " (" + calcPercent(atom, dimName) + ")"; - } - - addDim(def.html.escape(atom.dimension.type.label), valueLabel); - } - } - }, this); - - if(isMultiDatumGroup) { - if(anyCommonAtom){ - tooltip.push('
'); - } - - tooltip.push("#: " + group._datums.length + '
'); - - complexType - .sortDimensionNames(group.freeDimensionNames()) - .forEach(function(dimName){ - var dim = group.dimensions(dimName); - if(!dim.type.isHidden){ - var dimLabel = def.html.escape(dim.type.label), - valueLabel; - - if(dim.type.valueType === Number) { - // Sum - valueLabel = dim.format(dim.sum(visibleKeyArgs)); - if(playingPercentMap && playingPercentMap.has(dimName)) { - valueLabel += " (" + calcPercent(null, dimName) + ")"; - } - - dimLabel = "∑ " + dimLabel; - } else { - valueLabel = dim.atoms(visibleKeyArgs).map(function(atom){ return atom.label || "- "; }).join(", "); - } - - addDim(dimLabel, valueLabel); - } - }); - } - - return '
' + tooltip.join('\n') + '
'; - }, - - /* CLICK & DOUBLE-CLICK */ - _addPropClick: function(pvMark){ - var myself = this; - - function onClick(){ - var ev = arguments[arguments.length - 1]; - return myself._handleClick(this, ev); - } - - pvMark.cursor("pointer") - .event("click", onClick); - - this._ensurePropEvents(pvMark); - }, - - _addPropDoubleClick: function(pvMark){ - var myself = this; - - function onDoubleClick(){ - var ev = arguments[arguments.length - 1]; - return myself._handleDoubleClick(this, ev); - } - - pvMark.cursor("pointer") - .event("dblclick", onDoubleClick); - - this._ensurePropEvents(pvMark); - }, - - _isDoubleClickable: function(keyArgs){ - var options = keyArgs || this.chart.options; - return options.clickable && !!this.doubleClickAction; - }, - - _handleDoubleClick: function(pvMark, ev){ - if(!this._isDoubleClickable()){ - return; - } - - this._ignoreClicks = 2; - - var sign = pvMark.sign; - if(!sign || sign.isDoubleClickable()){ - var context = this._getContext(pvMark, ev); - this._onDoubleClick(context); - } - }, - - _onDoubleClick: function(context){ - var handler = this.doubleClickAction; - if(handler){ - if(this.compatVersion() <= 1){ - this._onV1DoubleClick(context, handler); - } else { - handler.call(context, context.scene); - } - } - }, - - _onV1DoubleClick: function(context, handler){ - handler.call(context.pvMark, - /* V1 ARGS */ - context.getV1Series(), - context.getV1Category(), - context.getV1Value(), - context.event, - context.getV1Datum()); - }, - - _isClickable: function(){ - return this.chart.options.clickable && !!this.clickAction; - }, - - _shouldHandleClick: function(){ - return this.chart._canSelectWithClick() || this._isClickable(); - }, - - _handleClick: function(pvMark, ev){ - if(!this._shouldHandleClick()){ - return; - } - - var options = this.chart.options, - context; - - if(!this.doubleClickAction){ - // Use shared context - context = this._getContext(pvMark, ev); - this._handleClickCore(context); - } else { - // Delay click evaluation so that - // it may be canceled if double click meanwhile - // fires. - var myself = this; - - // Capture current context - context = this._createContext(pvMark, ev); - /*global window:true*/ - window.setTimeout( - function(){ - myself._handleClickCore.call(myself, context); - }, - options.doubleClickMaxDelay || 300); - - } - }, - - _handleClickCore: function(context){ - if(this._ignoreClicks) { - this._ignoreClicks--; - } else { - var sign = context.sign; - if(!sign || sign.isClickable()){ - this._onClick(context); - } - - if((sign && sign.isSelectable()) || - (!sign && this.chart.options.selectable && context.scene.datum)){ - this._onSelect(context); - } - } - }, - - _onClick: function(context){ - var handler = this.clickAction; - if(handler){ - if(this.compatVersion() <= 1){ - this._onV1Click(context, handler); - } else { - handler.call(context, context.scene); - } - } - }, - - _onV1Click: function(context, handler){ - handler.call(context.pvMark, - /* V1 ARGS */ - context.getV1Series(), - context.getV1Category(), - context.getV1Value(), - context.event, - context.getV1Datum()); - }, - - /* SELECTION & RUBBER-BAND */ - _onSelect: function(context){ - var datums = context.scene.datums().array(); - if(datums.length){ - var chart = this.chart; - - chart._updatingSelections(function(){ - - datums = chart._onUserSelection(datums); - if(datums && datums.length){ - if(chart.options.ctrlSelectMode && !context.event.ctrlKey){ - chart.data.replaceSelected(datums); - } else { - pvc.data.Data.toggleSelected(datums); - } - } - }, this); - } - }, - - isRubberBandSelecting: function(){ - return this.topRoot._isRubberBandSelecting; - }, - - /** - * Add rubber-band functionality to panel. - * Override to prevent rubber band selection. - * - * @virtual - */ - _initRubberBand: function(){ - var myself = this, - chart = this.chart, - options = chart.options, - data = chart.data; - - var dMin2 = 4; // Minimum dx or dy, squared, for a drag to be considered a rubber band selection - - this._isRubberBandSelecting = false; - - // Rubber band - var rubberPvParentPanel = this.pvRootPanel || this.pvPanel.paddingPanel, - toScreen, - rb; - - var selectBar = - this.selectBar = - new pvc.visual.Bar(this, rubberPvParentPanel, { - extensionId: 'rubberBand', - normalStroke: true, - noHover: true, - noSelect: true, - noClick: true, - noDoubleClick: true, - noTooltip: true - }) - .override('defaultStrokeWidth', function(){ - return 1.5; - }) - .override('defaultColor', function(type){ - return type === 'stroke' ? - '#86fe00' : /* 'rgb(255,127,0)' */ - 'rgba(203, 239, 163, 0.6)' /* 'rgba(255, 127, 0, 0.15)' */ - ; - }) - .override('interactiveColor', function(color){ - return color; - }) - .pvMark - .lock('visible', function(){ return !!rb; }) - .lock('left', function(){ return rb.x; }) - .lock('right') - .lock('top', function(){ return rb.y; }) - .lock('bottom') - .lock('width', function(){ return rb.dx; }) - .lock('height', function(){ return rb.dy; }) - .lock('cursor') - .lock('events', 'none') - ; - - // IE must have a fill style to fire events - if(!this._getExtensionAbs('base', 'fillStyle')){ - rubberPvParentPanel.fillStyle(pvc.invisibleFill); - } - - // Require all events, wether it's painted or not - rubberPvParentPanel.lock('events', 'all'); - - // NOTE: Rubber band coordinates are always transformed to canvas/client - // coordinates (see 'select' and 'selectend' events) - - var scene = new pvc.visual.Scene(null, {panel: this}); - // Initialize x,y,dx and dy properties - scene.x = scene.y = scene.dx = scene.dy = 0; - - var selectionEndedDate; - rubberPvParentPanel - .lock('data', [scene]) - .event('mousedown', pv.Behavior.select().autoRender(false)) - .event('select', function(){ - if(!rb){ - if(myself.isAnimating()){ - return; - } - - if(scene.dx * scene.dx + scene.dy * scene.dy <= dMin2){ - return; - } - - rb = new pv.Shape.Rect(scene.x, scene.y, scene.dx, scene.dy); - - myself._isRubberBandSelecting = true; - - if(!toScreen){ - toScreen = rubberPvParentPanel.toScreenTransform(); - } - - myself.rubberBand = rb.apply(toScreen); - } else { - rb = new pv.Shape.Rect(scene.x, scene.y, scene.dx, scene.dy); - // not updating rubberBand ? - } - - selectBar.render(); - }) - .event('selectend', function(){ - if(rb){ - var ev = arguments[arguments.length - 1]; - - if(!toScreen){ - toScreen = rubberPvParentPanel.toScreenTransform(); - } - - //rb = new pv.Shape.Rect(scene.x, scene.y, scene.dx, scene.dy); - var rbs = rb.apply(toScreen); - - rb = null; - myself._isRubberBandSelecting = false; - selectBar.render(); // hide rubber band - - // Process selection - try{ - myself._processRubberBand(rbs, ev, {allowAdditive: true}); - } finally { - selectionEndedDate = new Date(); - } - } - }); - - if(options.clearSelectionMode === 'emptySpaceClick'){ - rubberPvParentPanel - .event("click", function() { - // It happens sometimes that the click is fired - // after mouse up, ending up clearing a just made selection. - if(selectionEndedDate){ - var timeSpan = new Date() - selectionEndedDate; - if(timeSpan < 300){ - selectionEndedDate = null; - return; - } - } - - if(data.owner.clearSelected()) { - myself.chart.updateSelections(); - } - }); - } - }, - - _processRubberBand: function(rb, ev, keyArgs){ - this.rubberBand = rb; - try{ - this._onRubberBandSelectionEnd(ev, keyArgs); - } finally { - this.rubberBand = null; - } - }, - - _onRubberBandSelectionEnd: function(ev, keyArgs){ - if(pvc.debug >= 10) { - this._log("rubberBand " + pvc.stringify(this.rubberBand)); - } - - keyArgs = Object.create(keyArgs || {}); - keyArgs.toggle = false; // output argument - - var datums = this._getDatumsOnRubberBand(ev, keyArgs); - if(datums){ - var allowAdditive = def.get(keyArgs, 'allowAdditive', true); - var chart = this.chart; - - //this._log("Selecting Datum count=" + datums.length + - // " keys=\n" + datums.map(function(d){return d.key;}).join('\n')); - - // Make sure selection changed action is called only once - // Checks if any datum's selected changed, at the end - chart._updatingSelections(function(){ - var clearBefore = !allowAdditive || - (!ev.ctrlKey && chart.options.ctrlSelectMode); - if(clearBefore){ - chart.data.owner.clearSelected(); - pvc.data.Data.setSelected(datums, true); - } else if(keyArgs.toggle){ - pvc.data.Data.toggleSelected(datums); - } else { - pvc.data.Data.setSelected(datums, true); - } - }); - - //this._log("End rubber band selection"); - } - }, - - _getDatumsOnRubberBand: function(ev, keyArgs){ - var datumMap = new def.Map(); - - this._getDatumsOnRect(datumMap, this.rubberBand, keyArgs); - - var datums = datumMap.values(); - if(datums.length){ - datums = this.chart._onUserSelection(datums); - if(datums && !datums.length){ - datums = null; - } - } - - return datums; - }, - - // Callback to handle end of rubber band selection - _getDatumsOnRect: function(datumMap, rect, keyArgs){ - this._getOwnDatumsOnRect(datumMap, rect, keyArgs); - - if(this._children) { - this._children.forEach(function(child){ - child._getDatumsOnRect(datumMap, rect, keyArgs); - }, this); - } - }, - - _getOwnDatumsOnRect: function(datumMap, rect, keyArgs){ - var any = false; - - if(this.isVisible){ - var pvMarks = this._getSelectableMarks(); - if(pvMarks && pvMarks.length){ - pvMarks.forEach(function(pvMark){ - this._eachMarkDatumOnRect(pvMark, rect, function(datum){ - datumMap.set(datum.id, datum); - any = true; - }, - this, - def.get(keyArgs, 'markSelectionMode')); - - }, this); - } - } - - return any; - }, - - _eachMarkDatumOnRect: function(pvMark, rect, fun, ctx, selectionMode){ - - var sign = pvMark.sign; - if(sign && !sign.isSelectable()){ - return; - } - - // center, partial and total (not implemented) - if(selectionMode == null){ - selectionMode = def.get(pvMark, 'rubberBandSelectionMode', 'partial'); - } - - var useCenter = (selectionMode === 'center'); - - pvMark.eachInstanceWithData(function(scenes, index, toScreen){ - - var shape = pvMark.getShape(scenes, index); - - shape = (useCenter ? shape.center() : shape).apply(toScreen); - - processShape.call(this, shape, scenes[index], index); - }, this); - - function processShape(shape, instance, index) { - if (shape.intersectsRect(rect)){ - var cccScene = instance.data; // exists for sure (ensured by eachInstanceWithData - if(cccScene && cccScene.datum){ - var group = cccScene.group; - var datums = group ? group._datums : def.array.as(cccScene.datum); - if(datums) { - datums.forEach(function(datum){ - if(!datum.isNull) { - if(pvc.debug >= 20) { - this._log("Rubbered Datum.key=" + datum.key + ": " + pvc.stringify(shape) + " mark type: " + pvMark.type + " index=" + index); - } - - fun.call(ctx, datum); - } - }, this); - } - } - } - } - }, - - /* ANCHORS & ORIENTATION */ - - /** - * Returns true if the anchor is one of the values 'top' or - * 'bottom'. - */ - isAnchorTopOrBottom: function(anchor) { - if (!anchor) { - anchor = this.anchor; - } - return anchor === "top" || anchor === "bottom"; - }, - - anchorOrtho: function(anchor) { - if (!anchor) { - anchor = this.anchor; - } - return pvc.BasePanel.relativeAnchor[anchor]; - }, - - anchorOrthoMirror: function(anchor) { - if (!anchor) { - anchor = this.anchor; - } - return pvc.BasePanel.relativeAnchorMirror[anchor]; - }, - - anchorOpposite: function(anchor) { - if (!anchor) { - anchor = this.anchor; - } - return pvc.BasePanel.oppositeAnchor[anchor]; - }, - - anchorLength: function(anchor) { - if (!anchor) { - anchor = this.anchor; - } - return pvc.BasePanel.parallelLength[anchor]; - }, - - anchorOrthoLength: function(anchor) { - if (!anchor) { - anchor = this.anchor; - } - return pvc.BasePanel.orthogonalLength[anchor]; - }, - - isOrientationVertical: function(orientation) { - return this.chart.isOrientationVertical(orientation); - }, - - isOrientationHorizontal: function(orientation) { - return this.chart.isOrientationHorizontal(orientation); - } -}) -.addStatic({ - // Determine what is the associated method to - // call to position the labels correctly - relativeAnchor: { - top: "left", - bottom: "left", - left: "bottom", - right: "bottom" - }, - - leftBottomAnchor: { - top: "bottom", - bottom: "bottom", - left: "left", - right: "left" - }, - - leftTopAnchor: { - top: "top", - bottom: "top", - left: "left", - right: "left" - }, - - horizontalAlign: { - top: "right", - bottom: "left", - middle: "center", - right: "right", - left: "left", - center: "center" - }, - - verticalAlign: { - top: "top", - bottom: "bottom", - middle: "middle", - right: "bottom", - left: "top", - center: "middle" - }, - - verticalAlign2: { - top: "top", - bottom: "bottom", - middle: "middle", - right: "top", - left: "bottom", - center: "middle" - }, - - relativeAnchorMirror: { - top: "right", - bottom: "right", - left: "top", - right: "top" - }, - - oppositeAnchor: { - top: "bottom", - bottom: "top", - left: "right", - right: "left" - }, - - parallelLength: { - top: "width", - bottom: "width", - right: "height", - left: "height" - }, - - orthogonalLength: { - top: "height", - bottom: "height", - right: "width", - left: "width" - }, - - oppositeLength: { - width: "height", - height: "width" - } -}); diff --git a/pacotes/ccc2/pvc/pvcBoxplotChart.js b/pacotes/ccc2/pvc/pvcBoxplotChart.js deleted file mode 100755 index 82655a0..0000000 --- a/pacotes/ccc2/pvc/pvcBoxplotChart.js +++ /dev/null @@ -1,130 +0,0 @@ - -/** - * BoxplotChart is the main class for generating... categorical boxplotcharts. - * - * The boxplot is used to represent the distribution of data using: - * - a box to represent the region that contains 50% of the datapoints, - * - the whiskers to represent the regions that contains 95% of the datapoints, and - * - a center line (in the box) that represents the median of the dataset. - * For more information on boxplots you can visit http://en.wikipedia.org/wiki/Box_plot - * - * If you have an issue or suggestions regarding the ccc BoxPlot-charts - * please contact CvK at cde@vinzi.nl - */ -def -.type('pvc.BoxplotChart', pvc.CategoricalAbstract) -.add({ - _processOptionsCore: function(options){ - this.base.apply(this, arguments); - - // Not supported - options.stacked = false; - }, - - /** - * Initializes each chart's specific roles. - * @override - */ - _initVisualRoles: function(){ - - this.base(); - - var roleSpecBase = { - isMeasure: true, - requireSingleDimension: true, - requireIsDiscrete: false, - valueType: Number - }; - - [ - {name: 'median', label: 'Median', defaultDimension: 'median', isRequired: true}, - {name: 'lowerQuartil', label: 'Lower Quartil', defaultDimension: 'lowerQuartil'}, - {name: 'upperQuartil', label: 'Upper Quartil', defaultDimension: 'upperQuartil'}, - {name: 'minimum', label: 'Minimum', defaultDimension: 'minimum' }, - {name: 'maximum', label: 'Maximum', defaultDimension: 'maximum'} - ].forEach(function(info){ - this._addVisualRole(info.name, def.create(roleSpecBase, info)); - }, this); - }, - - _getTranslationClass: function(translOptions){ - return def - .type(this.base(translOptions)) - .add(pvc.data.BoxplotChartTranslationOper); - }, - - _initPlotsCore: function(/*hasMultiRole*/){ - new pvc.visual.BoxPlot(this); - - if(this.options.plot2){ - this._animatable = true; - // Line Plot - new pvc.visual.PointPlot(this, { - name: 'plot2', - defaults: { - LinesVisible: true, - DotsVisible: true, - OrthoRole: 'median', - ColorAxis: 2 - }, - fixed: { - OrthoAxis: 1 - }}); - } - }, - - _bindAxes: function(hasMultiRole){ - - this.base(hasMultiRole); - - // Set defaults of Offset property - var typeAxes = this.axesByType.ortho; - if(typeAxes){ - typeAxes.forEach(function(axis){ - axis.option.defaults({Offset: 0.02}); - }); - } - }, - - /* @override */ - _createPlotPanels: function(parentPanel, baseOptions){ - var plots = this.plots; - - var boxPlot = plots.box; - - var boxPanel = new pvc.BoxplotPanel( - this, - parentPanel, - boxPlot, - Object.create(baseOptions)); - - // v1 field - this.bpChartPanel = boxPanel; - - var plot2Plot = plots.plot2; - if(plot2Plot){ - if(pvc.debug >= 3){ - this._log("Creating Point panel."); - } - - var pointPanel = new pvc.PointPanel( - this, - parentPanel, - plot2Plot, - Object.create(baseOptions)); - - // HACK: - pointPanel._v1DimRoleName.value = plot2Plot.option('OrthoRole'); - } - }, - - defaults: { - // plot2: false - // legend: false, - crosstabMode: false - // panelSizeRatio - } -}) -.addStatic({ - measureRolesNames: ['median', 'lowerQuartil', 'upperQuartil', 'minimum', 'maximum'] -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcBoxplotPanel.js b/pacotes/ccc2/pvc/pvcBoxplotPanel.js deleted file mode 100755 index 8ba7748..0000000 --- a/pacotes/ccc2/pvc/pvcBoxplotPanel.js +++ /dev/null @@ -1,332 +0,0 @@ - -def -.type('pvc.BoxplotPanel', pvc.CategoricalAbstractPanel) -.init(function(chart, parent, plot, options) { - - this.base(chart, parent, plot, options); - - this.boxSizeRatio = plot.option('BoxSizeRatio'); - this.maxBoxSize = plot.option('BoxSizeMax'); -}) -.add({ - plotType: 'box', - - anchor: 'fill', - - // Override default mappings - _v1DimRoleName: { - //'series': 'series', - //'category': 'category', - 'value': 'median' - }, - - /** - * @override - */ - _createCore: function(){ - - this.base(); - - var rootScene = this._buildScene(); - - var a_bottom = this.isOrientationVertical() ? "bottom" : "left", - a_left = this.anchorOrtho(a_bottom), - a_width = this.anchorLength(a_bottom), - a_height = this.anchorOrthoLength(a_bottom) - ; - - function defaultColor(type){ - var color = this.base(type); - return type === 'stroke' ? color.darker(1) : color; - } - - /* Category Panel */ - var extensionIds = ['panel']; - if(this.compatVersion() <= 1){ - extensionIds.push(''); // let access as "box_" - } - - this.pvBoxPanel = new pvc.visual.Panel(this, this.pvPanel, { - extensionId: extensionIds - }) - .lock('data', rootScene.childNodes) - .lockMark(a_left, function(scene){ - var catVar = scene.vars.category; - return catVar.x - catVar.width / 2; - }) - .pvMark - [a_width](function(scene){ return scene.vars.category.width; }) - ; - - /* V Rules */ - function setupRuleWhisker(rule){ - rule.lock(a_left, function(){ - return this.pvMark.parent[a_width]() / 2; - }) - .override('defaultColor', defaultColor) - ; - - return rule; - } - - this.pvRuleWhiskerUpper = setupRuleWhisker(new pvc.visual.Rule(this, this.pvBoxPanel, { - extensionId: 'boxRuleWhisker', - freePosition: true, - noHover: false, - noSelect: false, - noClick: false, - noDoubleClick: false - })) - .intercept('visible', function(scene){ - return scene.vars.category.showRuleWhiskerUpper && this.delegateExtension(true); - }) - .lock(a_bottom, function(scene){ return scene.vars.category.ruleWhiskerUpperBottom; }) - .lock(a_height, function(scene){ return scene.vars.category.ruleWhiskerUpperHeight; }) - .pvMark - ; - - this.pvRuleWhiskerLower = setupRuleWhisker(new pvc.visual.Rule(this, this.pvBoxPanel, { - extensionId: 'boxRuleWhisker', - freePosition: true, - noHover: false, - noSelect: false, - noClick: false, - noDoubleClick: false - })) - .intercept('visible', function(scene){ - return scene.vars.category.showRuleWhiskerBelow && this.delegateExtension(true); - }) - .lock(a_bottom, function(scene){ return scene.vars.category.ruleWhiskerLowerBottom; }) - .lock(a_height, function(scene){ return scene.vars.category.ruleWhiskerLowerHeight; }) - .pvMark - ; - - /* Box Bar */ - function setupHCateg(sign){ - sign.lock(a_left, function(scene){ return scene.vars.category.boxLeft; }) - .lock(a_width, function(scene){ return scene.vars.category.boxWidth; }) - ; - - return sign; - } - - this.pvBar = setupHCateg(new pvc.visual.Bar(this, this.pvBoxPanel, { - extensionId: 'boxBar', - freePosition: true, - normalStroke: true - })) - .intercept('visible', function(scene){ - return scene.vars.category.showBox && this.delegateExtension(true); - }) - .lock(a_bottom, function(scene){ return scene.vars.category.boxBottom; }) - .lock(a_height, function(scene){ return scene.vars.category.boxHeight; }) - .override('defaultColor', defaultColor) - .override('defaultStrokeWidth', def.fun.constant(1)) - .pvMark - ; - - /* H Rules */ - function setupHRule(rule){ - setupHCateg(rule); - - rule.override('defaultColor', defaultColor); - - return rule; - } - - this.pvRuleMin = setupHRule(new pvc.visual.Rule(this, this.pvBoxPanel, { - extensionId: 'boxRuleMin', - freePosition: true, - noHover: false, - noSelect: false, - noClick: false, - noDoubleClick: false - })) - .intercept('visible', function(){ - return this.scene.vars.minimum.value != null && this.delegateExtension(true); - }) - .lock(a_bottom, function(){ return this.scene.vars.minimum.position; }) // bottom - .pvMark - ; - - this.pvRuleMax = setupHRule(new pvc.visual.Rule(this, this.pvBoxPanel, { - extensionId: 'boxRuleMax', - freePosition: true, - noHover: false, - noSelect: false, - noClick: false, - noDoubleClick: false - })) - .intercept('visible', function(){ - return this.scene.vars.maximum.value != null && this.delegateExtension(true); - }) - .lock(a_bottom, function(){ return this.scene.vars.maximum.position; }) // bottom - .pvMark - ; - - this.pvRuleMedian = setupHRule(new pvc.visual.Rule(this, this.pvBoxPanel, { - extensionId: 'boxRuleMedian', - freePosition: true, - noHover: false, - noSelect: false, - noClick: false, - noDoubleClick: false - })) - .intercept('visible', function(){ - return this.scene.vars.median.value != null && this.delegateExtension(true); - }) - .lock(a_bottom, function(){ return this.scene.vars.median.position; }) // bottom - .override('defaultStrokeWidth', def.fun.constant(2)) - .pvMark - ; - }, - - /** - * Renders this.pvScatterPanel - the parent of the marks that are affected by interaction changes. - * @override - */ - renderInteractive: function(){ - this.pvBoxPanel.render(); - }, - - /** - * Returns an array of marks whose instances are associated to a datum or group, or null. - * @override - */ - _getSelectableMarks: function(){ - return [this.pvBar]; - }, - - _buildScene: function(){ - var chart = this.chart, - measureRolesDimNames = def.query(chart.measureVisualRoles()).object({ - name: function(role){ return role.name; }, - value: function(role){ return role.firstDimensionName(); } - }), - visibleKeyArgs = {visible: true, zeroIfNone: false}, - data = this.visibleData(), - rootScene = new pvc.visual.Scene(null, {panel: this, group: data}), - baseScale = this.axes.base.scale, - bandWidth = baseScale.range().band, - boxWidth = Math.min(bandWidth * this.boxSizeRatio, this.maxBoxSize), - orthoScale = this.axes.ortho.scale, - colorVarHelper = new pvc.visual.RoleVarHelper(chart, chart._colorRole) - ; - - /** - * Create starting scene tree - */ - data.children() // categories - .each(createCategScene, this); - - return rootScene; - - function createCategScene(categData){ - var categScene = new pvc.visual.Scene(rootScene, {group: categData}); - var vars = categScene.vars; - - // Series distinction is ignored - // If the role is bound by the user, its data will not be visible - vars.series = new pvc.visual.ValueLabelVar(null, ""); - var catVar = vars.category = new pvc.visual.ValueLabelVar(categData.value, categData.label); - - def.set(catVar, - 'group', categData, - 'x', baseScale(categData.value), - 'width', bandWidth, - 'boxWidth', boxWidth, - 'boxLeft', bandWidth / 2 - boxWidth / 2); - - chart.measureVisualRoles().forEach(function(role){ - var dimName = measureRolesDimNames[role.name], - svar; - - if(dimName){ - var dim = categData.dimensions(dimName), - value = dim.sum(visibleKeyArgs); - - svar = new pvc.visual.ValueLabelVar(value, dim.format(value)); - svar.position = orthoScale(value); - } else { - svar = new pvc.visual.ValueLabelVar(null, ""); - svar.position = null; - } - - vars[role.name] = svar; - }); - - colorVarHelper.onNewScene(categScene, /* isLeaf */ true); - - // ------------ - - var hasMin = vars.minimum.value != null, - hasLower = vars.lowerQuartil.value != null, - hasMedian = vars.median.value != null, - hasUpper = vars.upperQuartil.value != null, - bottom, - top; - - var show = hasLower || hasUpper; - if(show){ - bottom = hasLower ? vars.lowerQuartil.position : - hasMedian ? vars.median.position : - vars.upperQuartil.position - ; - - top = hasUpper ? vars.upperQuartil.position : - hasMedian ? vars.median.position : - vars.lowerQuartil.position - ; - - show = (top !== bottom); - if(show){ - catVar.boxBottom = bottom; - catVar.boxHeight = top - bottom; - } - } - - catVar.showBox = show; - - // vRules - show = vars.maximum.value != null; - if(show){ - bottom = hasUpper ? vars.upperQuartil.position : - hasMedian ? vars.median.position : - hasLower ? vars.lowerQuartil.position : - hasMin ? vars.minimum.position : - null - ; - - show = bottom != null; - if(show){ - catVar.ruleWhiskerUpperBottom = bottom; - catVar.ruleWhiskerUpperHeight = vars.maximum.position - bottom; - } - } - - catVar.showRuleWhiskerUpper = show; - - // ---- - - show = hasMin; - if(show){ - top = hasLower ? vars.lowerQuartil.position : - hasMedian ? vars.median.position : - hasUpper ? vars.upperQuartil.position : - null - ; - - show = top != null; - if(show){ - bottom = vars.minimum.position; - catVar.ruleWhiskerLowerHeight = top - bottom; - catVar.ruleWhiskerLowerBottom = bottom; - } - } - - catVar.showRuleWhiskerBelow = show; - - // hasMin = vars.minimum.value != null, - } - } -}); diff --git a/pacotes/ccc2/pvc/pvcBulletChart.js b/pacotes/ccc2/pvc/pvcBulletChart.js deleted file mode 100755 index ed43fdd..0000000 --- a/pacotes/ccc2/pvc/pvcBulletChart.js +++ /dev/null @@ -1,517 +0,0 @@ - -/** - * Bullet chart generation - */ -def -.type('pvc.BulletChart', pvc.BaseChart) -.init(function(options){ - - options = options || {}; - - // Add range and marker dimension group defaults - // This only helps in default bindings... - var dimGroups = options.dimensionGroups || (options.dimensionGroups = {}); - var rangeDimGroup = dimGroups.range || (dimGroups.range = {}); - if(rangeDimGroup.valueType === undefined){ - rangeDimGroup.valueType = Number; - } - - var markerDimGroup = dimGroups.marker || (dimGroups.marker = {}); - if(markerDimGroup.valueType === undefined){ - markerDimGroup.valueType = Number; - } - - this.base(options); -}) -.add({ - - bulletChartPanel : null, - allowNoData: true, - - /** - * @override - */ - _processOptionsCore: function(options){ - - this.base(options); - - options.legend = false; - options.selectable = false; // not supported yet - }, - - /** - * Initializes each chart's specific roles. - * @override - */ - _initVisualRoles: function(){ - - this.base(); - - this._addVisualRole('title', { defaultDimension: 'title*' }); - this._addVisualRole('subTitle', { defaultDimension: 'subTitle*' }); - this._addVisualRole('value', { - //isRequired: true, // due to the no data mode - isMeasure: true, - requireIsDiscrete: false, - valueType: Number, - defaultDimension: 'value*' - }); - this._addVisualRole('marker', { - isMeasure: true, - requireIsDiscrete: false, - valueType: Number, - defaultDimension: 'marker*' - }); - this._addVisualRole('range', { - isMeasure: true, - requireIsDiscrete: false, - valueType: Number, - defaultDimension: 'range*' - }); - }, - - _createTranslation: function(translOptions){ - - var translation = this.base(translOptions), - /* - * By now the translation has already been initialized - * and its virtualItemSize is determined. - */ - size = translation.virtualItemSize() - ; - - /* Configure the translation with default dimensions. - * 1 Value - * 2 Title | Value - * 3 Title | Value | Marker - * >= 4 Title | Subtitle | Value | Marker | Ranges - */ - // TODO: respect user reader definitions (names and indexes) - // TODO: create a translator class for this, like with the boxplot? - if(size){ - switch(size){ - case 1: - translation.defReader({names: 'value'}); - break; - - case 2: - translation.defReader({names: ['title', 'value']}); - break; - - case 3: - translation.defReader({names: ['title', 'value', 'marker']}); - break; - - default: - translation.defReader({names: ['title', 'subTitle', 'value', 'marker']}); - if(size > 4){ - // 4, 5, 6, ... - translation.defReader({names: 'range', indexes: pv.range(4, size)}); - } - break; - } - } - - return translation; - }, - - _initPlotsCore: function(hasMultiRole){ - new pvc.visual.BulletPlot(this); - }, - - _preRenderContent: function(contentOptions){ - var bulletPlot = this.plots.bullet; - this.bulletChartPanel = new pvc.BulletChartPanel( - this, - this.basePanel, - bulletPlot, - def.create(contentOptions, { - tooltipEnabled: this._tooltipEnabled - })); - }, - - defaults: { - compatVersion: 1, - - orientation: 'horizontal', - - bulletSize: 30, // Bullet size - bulletSpacing: 50, // Spacing between bullets - bulletMargin: 100, // Left margin - - // Defaults -// bulletMarkers: null, // Array of markers to appear -// bulletMeasures: null, // Array of measures -// bulletRanges: null, // Ranges - bulletTitle: "Title", // Title - bulletSubtitle: "", // Subtitle - bulletTitlePosition: "left", // Position of bullet title relative to bullet - -// axisDoubleClickAction: null, - tooltipFormat: function(s, c, v) { - return this.chart.options.valueFormat(v); - }, - - crosstabMode: false, - seriesInRows: false - } -}); - -/* - * Bullet chart panel. Generates a bar chart. Specific options are: - * orientation - horizontal or vertical. Default: vertical - * - * Has the following protovis extension points: - * - * chart_ - for the main chart Panel - * bulletsPanel_ - for the bullets panel - * bulletPanel_ - for the bullets pv.Layout.Bullet - * bulletRange_ - for the bullet range - * bulletMeasure_ - for the bullet measure - * bulletMarker_ - for the marker - * bulletRule_ - for the axis rule - * bulletRuleLabel_ - for the axis rule label - * bulletTitle_ - for the bullet title - * bulletSubtitle_ - for the main bar label - */ - - -def -.type('pvc.BulletChartPanel', pvc.PlotPanel) -.add({ - pvBullets: null, - pvBullet: null, - data: null, - onSelectionChange: null, - - /** - * @override - */ - _createCore: function(layoutInfo) { - var chart = this.chart, - options = chart.options, - data = this.buildData(); - - var anchor = options.orientation=="horizontal"?"left":"bottom"; - var size, angle, align, titleLeftOffset, titleTopOffset, ruleAnchor, leftPos, topPos, titleSpace; - - if(options.orientation=="horizontal"){ - size = layoutInfo.clientSize.width - this.chart.options.bulletMargin - 20; - angle=0; - switch (options.bulletTitlePosition) { - case 'top': - leftPos = this.chart.options.bulletMargin; - titleLeftOffset = 0; - align = 'left'; - titleTopOffset = -12; - titleSpace = parseInt(options.titleSize/2, 10); - break; - case 'bottom': - leftPos = this.chart.options.bulletMargin; - titleLeftOffset = 0; - align = 'left'; - titleTopOffset = options.bulletSize + 32; - titleSpace = 0; - break; - case 'right': - leftPos = 5; - titleLeftOffset = size + 5; - align = 'left'; - titleTopOffset = parseInt(options.bulletSize/2, 10); - titleSpace = 0; - break; - case 'left': - // The next comment is for JSHint - /* falls through */ - default: - leftPos = this.chart.options.bulletMargin; - titleLeftOffset = 0; - titleTopOffset = parseInt(options.bulletSize/2, 10); - align = 'right'; - titleSpace = 0; - } - ruleAnchor = "bottom"; - topPos = function(){ - // TODO: 10 - return (this.index * (options.bulletSize + options.bulletSpacing)) + titleSpace; - }; - } else { - size = layoutInfo.clientSize.height - this.chart.options.bulletMargin - 20; - switch (options.bulletTitlePosition) { - case 'top': - leftPos = this.chart.options.bulletMargin; - titleLeftOffset = 0; - align = 'left'; - titleTopOffset = -20; - angle = 0; - topPos = undefined; - break; - case 'bottom': - leftPos = this.chart.options.bulletMargin; - titleLeftOffset = 0; - align = 'left'; - titleTopOffset = size + 20; - angle = 0; - topPos = 20; - break; - case 'right': - leftPos = 5; - titleLeftOffset = this.chart.options.bulletSize + 40; - align = 'left'; - titleTopOffset = size; - angle = -Math.PI/2; - topPos = undefined; - break; - case 'left': - // The next comment is for JSHint - /* falls through */ - default: - leftPos = this.chart.options.bulletMargin; - titleLeftOffset = -12; - titleTopOffset = this.height - this.chart.options.bulletMargin - 20; - align = 'left'; - angle = -Math.PI/2; - topPos = undefined; - } - ruleAnchor = "right"; - leftPos = function(){ - return options.bulletMargin + this.index * (options.bulletSize + options.bulletSpacing); - }; - - } - - this.pvBullets = this.pvPanel.add(pv.Panel) - .data(data) - [pvc.BasePanel.orthogonalLength[anchor]](size) - [pvc.BasePanel.parallelLength[anchor]](this.chart.options.bulletSize) - .margin(20) - .left(leftPos) - .top(topPos); - - - this.pvBullet = this.pvBullets.add(pv.Layout.Bullet) - .orient (anchor) - .ranges (function(d){ return d.ranges; }) - .measures(function(d){ return d.measures; }) - .markers (function(d){ return d.markers; }); - - if (options.clickable && this.clickAction){ - var me = this; - - this.pvBullet - .cursor("pointer") - .event("click",function(d){ - var s = d.title; - var c = d.subtitle; - var ev = pv.event; - return me.clickAction(s,c, d.measures, ev); - }); - } - - this.pvBulletRange = this.pvBullet.range.add(pv.Bar); - - this.pvBulletMeasure = this.pvBullet.measure.add(pv.Bar) - .text(function(v, d){ - return d.formattedMeasures[this.index]; - }); - - this.pvBulletMarker = this.pvBullet.marker.add(pv.Dot) - .shape("square") - .fillStyle("white") - .text(function(v, d){ - return d.formattedMarkers[this.index]; - }); - - if(this.tooltipEnabled){ - // Extend default - // TODO: how to deal with different measures in tooltips depending on mark - - // this._addPropTooltip(this.pvBulletMeasure); - // this._addPropTooltip(this.pvBulletMarker); - var myself = this; - this.pvBulletMeasure - .localProperty('tooltip') - .tooltip(function(v, d){ - var s = d.title; - var c = d.subtitle; - return chart.options.tooltipFormat.call(myself,s,c,v); - }) - ; - - this.pvBulletMarker - .localProperty('tooltip') - .tooltip(function(v, d){ - var s = d.title; - var c = d.subtitle; - return chart.options.tooltipFormat.call(myself,s,c,v); - }) - ; - - this.pvBulletMeasure.event("mouseover", pv.Behavior.tipsy(this.chart._tooltipOptions)); - this.pvBulletMarker .event("mouseover", pv.Behavior.tipsy(this.chart._tooltipOptions)); - } - - this.pvBulletRule = this.pvBullet.tick.add(pv.Rule); - - this.pvBulletRuleLabel = this.pvBulletRule.anchor(ruleAnchor).add(pv.Label) - .text(this.pvBullet.x.tickFormat); - - this.pvBulletTitle = this.pvBullet.anchor(anchor).add(pv.Label) - .font("bold 12px sans-serif") - .textAngle(angle) - .left(-10) - .textAlign(align) - .textBaseline("bottom") - .left(titleLeftOffset) - .top(titleTopOffset) - .text(function(d){ - return d.formattedTitle; - }); - - this.pvBulletSubtitle = this.pvBullet.anchor(anchor).add(pv.Label) - .textStyle("#666") - .textAngle(angle) - .textAlign(align) - .textBaseline("top") - .left(titleLeftOffset) - .top(titleTopOffset) - .text(function(d){ - return d.formattedSubtitle; - }); - - var doubleClickAction = (typeof(options.axisDoubleClickAction) == 'function') ? - function(d, e) { - //ignoreClicks = 2; - options.axisDoubleClickAction(d, e); - - } : null; - - if (options.clickable && doubleClickAction) { - this.pvBulletTitle - .cursor("pointer") - .events('all') //labels don't have events by default - .event("dblclick", function(d){ - doubleClickAction(d, arguments[arguments.length-1]); - }); - - this.pvBulletSubtitle - .cursor("pointer") - .events('all') //labels don't have events by default - .event("dblclick", function(d){ - doubleClickAction(d, arguments[arguments.length-1]); - }); - - } - }, - - applyExtensions: function(){ - - this.base(); - - this.extend(this.pvBullets,"bulletsPanel"); - this.extend(this.pvBullet,"bulletPanel"); - this.extend(this.pvBulletRange,"bulletRange"); - this.extend(this.pvBulletMeasure,"bulletMeasure"); - this.extend(this.pvBulletMarker,"bulletMarker"); - this.extend(this.pvBulletRule,"bulletRule"); - this.extend(this.pvBulletRuleLabel,"bulletRuleLabel"); - this.extend(this.pvBulletTitle,"bulletTitle"); - this.extend(this.pvBulletSubtitle,"bulletSubtitle"); - }, - - _getExtensionId: function(){ - // content coincides, visually in this chart type - return [{abs: 'content'}].concat(this.base()); - }, - - /* - * Data array to back up bullet charts. - */ - buildData: function(){ - var data, - chart = this.chart, - options = chart.options, - - titleRole = chart.visualRoles('title'), - titleGrouping = titleRole.grouping, - - subTitleRole = chart.visualRoles('subTitle'), - subTitleGrouping = subTitleRole.grouping, - - valueRole = chart.visualRoles('value'), - valueGrouping = valueRole.grouping, - - markerRole = chart.visualRoles('marker'), - markerGrouping = markerRole.grouping, - - rangeRole = chart.visualRoles('range'), - rangeGrouping = rangeRole.grouping; - - var defaultData = { - title: options.bulletTitle, - formattedTitle: options.bulletTitle, - - subtitle: options.bulletSubtitle, - formattedSubtitle: options.bulletSubtitle, - - ranges: def.array.to(options.bulletRanges) || [], - measures: def.array.to(options.bulletMeasures) || [], - markers: def.array.to(options.bulletMarkers) || [] - }; - - def.set(defaultData, - 'formattedRanges', defaultData.ranges .map(String), - 'formattedMeasures', defaultData.measures.map(String), - 'formattedMarkers', defaultData.markers .map(String) - ); - - if(!valueGrouping && - !titleGrouping && - !markerGrouping && - !subTitleGrouping && - !rangeGrouping){ - - data = [defaultData]; - } else { - data = chart.data.datums().select(function(datum){ - var d = Object.create(defaultData), - view; - - if(valueGrouping){ - view = valueGrouping.view(datum); - d.measures = view.values(); - d.formattedMeasures = view.labels(); - } - - if(titleGrouping){ - view = titleGrouping.view(datum); - d.title = view.value; - d.formattedTitle = view.label; - } - - if(subTitleGrouping){ - view = subTitleGrouping.view(datum); - d.subtitle = view.value; - d.formattedSubtitle = view.label; - } - - if(markerGrouping){ - view = markerGrouping.view(datum); - d.markers = view.values(); - d.formattedMarkers = view.labels(); - } - - if(rangeGrouping){ - view = rangeGrouping.view(datum); - d.ranges = view.values(); - d.formattedRanges = view.labels(); - } - - return d; - }, this) - .array(); - } - - return data; - } -}); diff --git a/pacotes/ccc2/pvc/pvcCartesianAbstract.js b/pacotes/ccc2/pvc/pvcCartesianAbstract.js deleted file mode 100755 index 560aed2..0000000 --- a/pacotes/ccc2/pvc/pvcCartesianAbstract.js +++ /dev/null @@ -1,725 +0,0 @@ - -/** - * CartesianAbstract is the base class for all 2D cartesian space charts. - */ -def -.type('pvc.CartesianAbstract', pvc.BaseChart) -.init(function(options){ - - this.axesPanels = {}; - - this.base(options); -}) -.add({ - _gridDockPanel: null, - - axesPanels: null, - - // V1 properties - yAxisPanel: null, - xAxisPanel: null, - secondXAxisPanel: null, - secondYAxisPanel: null, - yScale: null, - xScale: null, - - _getSeriesRoleSpec: function(){ - return { isRequired: true, defaultDimension: 'series*', autoCreateDimension: true, requireIsDiscrete: true }; - }, - - _getColorRoleSpec: function(){ - return { isRequired: true, defaultDimension: 'color*', defaultSourceRole: 'series', requireIsDiscrete: true }; - }, - - _collectPlotAxesDataCells: function(plot, dataCellsByAxisTypeThenIndex){ - - this.base(plot, dataCellsByAxisTypeThenIndex); - - /* NOTE: Cartesian axes are created even when hasMultiRole && !parent - * because it is needed to read axis options in the root chart. - * Also binding occurs to be able to know its scale type. - * Yet, their scales are not setup at the root level. - */ - - /* Configure Base Axis Data Cell */ - if(plot.option.isDefined('BaseAxis')){ - var baseDataCellsByAxisIndex = - def - .array - .lazy(dataCellsByAxisTypeThenIndex, 'base'); - - def - .array - .lazy(baseDataCellsByAxisIndex, plot.option('BaseAxis') - 1) - .push({ - plot: plot, - role: this.visualRoles(plot.option('BaseRole')), - dataPartValue: plot.option('DataPart') - }); - } - - /* Configure Ortho Axis Data Cell */ - if(plot.option.isDefined('OrthoAxis')){ - - var trend = plot.option('Trend'); - var isStacked = plot.option.isDefined('Stacked') ? - plot.option('Stacked') : - undefined; - - var orthoDataCellsByAxisIndex = - def - .array - .lazy(dataCellsByAxisTypeThenIndex, 'ortho'); - - var orthoRoleNames = def.array.to(plot.option('OrthoRole')); - - var dataCellBase = { - dataPartValue: plot.option('DataPart' ), - isStacked: isStacked, - trend: trend, - nullInterpolationMode: plot.option('NullInterpolationMode') - }; - - var orthoDataCells = - def - .array - .lazy(orthoDataCellsByAxisIndex, plot.option('OrthoAxis') - 1); - - orthoRoleNames.forEach(function(orthoRoleName){ - var dataCell = Object.create(dataCellBase); - dataCell.role = this.visualRoles(orthoRoleName); - orthoDataCells.push(dataCell); - }, this) - ; - } - }, - - _addAxis: function(axis){ - this.base(axis); - - switch(axis.type){ - case 'base': - case 'ortho': - this.axes[axis.orientedId] = axis; - if(axis.v1SecondOrientedId){ - this.axes[axis.v1SecondOrientedId] = axis; - } - break; - } - - return this; - }, - - _generateTrendsDataCell: function(dataCell){ - /*jshint onecase:true */ - var trend = dataCell.trend; - if(trend){ - var trendInfo = pvc.trends.get(trend.type); - - var newDatums = []; - - this._generateTrendsDataCellCore(newDatums, dataCell, trendInfo); - - if(newDatums.length){ - this.data.owner.add(newDatums); - } - } - }, - - _generateTrendsDataCellCore: function(dataCell, trendInfo){ - // abstract - // see Metric and Categorical implementations - }, - - _setAxesScales: function(hasMultiRole){ - - this.base(hasMultiRole); - - if(!hasMultiRole || this.parent){ - ['base', 'ortho'].forEach(function(type){ - var axisOfType = this.axesByType[type]; - if(axisOfType){ - axisOfType.forEach(this._createAxisScale, this); - } - }, this); - } - }, - - /** - * Creates a scale for a given axis, with domain applied, but no range yet, - * assigns it to the axis and assigns the scale to special v1 chart instance fields. - * - * @param {pvc.visual.CartesianAxis} axis The axis. - * @type pv.Scale - */ - _createAxisScale: function(axis){ - var isOrtho = axis.type === 'ortho'; - var isCart = isOrtho || axis.type === 'base'; - - var scale = this._createScaleByAxis(axis); - if(scale.isNull && pvc.debug >= 3){ - this._log(def.format("{0} scale for axis '{1}'- no data", [axis.scaleType, axis.id])); - } - - scale = axis.setScale(scale).scale; - - if(isCart){ - /* V1 fields xScale, yScale, secondScale */ - if(isOrtho && axis.index === 1) { - this.secondScale = scale; - } else if(!axis.index) { - this[axis.orientation + 'Scale'] = scale; - } - } - - return scale; - }, - - /** - * Creates a scale for a given axis. - * - * @param {pvc.visual.CartesianAxis} axis The axis. - * @type pv.Scale - */ - _createScaleByAxis: function(axis){ - var createScale = this['_create' + def.firstUpperCase(axis.scaleType) + 'ScaleByAxis']; - - return createScale.call(this, axis); - }, - - _preRenderContent: function(contentOptions){ - - this._createFocusWindow(); - - /* Create the grid/docking panel */ - this._gridDockPanel = new pvc.CartesianGridDockingPanel(this, this.basePanel, { - margins: contentOptions.margins, - paddings: contentOptions.paddings - }); - - /* Create child axis panels - * The order is relevant because of docking order. - */ - ['base', 'ortho'].forEach(function(type){ - var typeAxes = this.axesByType[type]; - if(typeAxes){ - def - .query(typeAxes) - .reverse() - .each(function(axis){ - this._createAxisPanel(axis); - }, this) - ; - } - }, this); - - /* Create main content panel - * (something derived from pvc.CartesianAbstractPanel) */ - this._createPlotPanels(this._gridDockPanel, { - clickAction: contentOptions.clickAction, - doubleClickAction: contentOptions.doubleClickAction - }); - }, - - _createFocusWindow: function(){ - if(this._canSelectWithFocusWindow()){ - // In case we're being re-rendered, - // capture the axes' focuaWindow, if any. - // and set it as the next focusWindow. - var fwData; - var fw = this.focusWindow; - if(fw){ - fwData = fw._exportData(); - } - - fw = this.focusWindow = new pvc.visual.CartesianFocusWindow(this); - - if(fwData){ - fw._importData(fwData); - } - - fw._initFromOptions(); - - } else if(this.focusWindow){ - delete this.focusWindow; - } - }, - - /** - * Creates an axis panel, if it is visible. - * @param {pvc.visual.CartesianAxis} axis The cartesian axis. - * @type pvc.AxisPanel - */ - _createAxisPanel: function(axis){ - if(axis.option('Visible')) { - var titlePanel; - var title = axis.option('Title'); - if (!def.empty(title)) { - titlePanel = new pvc.AxisTitlePanel(this, this._gridDockPanel, axis, { - title: title, - font: axis.option('TitleFont') || axis.option('Font'), - anchor: axis.option('Position'), - align: axis.option('TitleAlign'), - margins: axis.option('TitleMargins'), - paddings: axis.option('TitlePaddings'), - titleSize: axis.option('TitleSize'), - titleSizeMax: axis.option('TitleSizeMax') - }); - } - - var panel = new pvc.AxisPanel(this, this._gridDockPanel, axis, { - anchor: axis.option('Position'), - size: axis.option('Size'), - sizeMax: axis.option('SizeMax'), - clickAction: axis.option('ClickAction'), - doubleClickAction: axis.option('DoubleClickAction'), - useCompositeAxis: axis.option('Composite'), - font: axis.option('Font'), - labelSpacingMin: axis.option('LabelSpacingMin'), - tickExponentMin: axis.option('TickExponentMin'), - tickExponentMax: axis.option('TickExponentMax'), - grid: axis.option('Grid'), - gridCrossesMargin: axis.option('GridCrossesMargin'), - ruleCrossesMargin: axis.option('RuleCrossesMargin'), - zeroLine: axis.option('ZeroLine'), - domainRoundMode: axis.option('DomainRoundMode'), - desiredTickCount: axis.option('DesiredTickCount'), - showTicks: axis.option('Ticks'), - showMinorTicks: axis.option('MinorTicks') - }); - - if(titlePanel){ - panel.titlePanel = titlePanel; - } - - this.axesPanels[axis.id] = panel; - this.axesPanels[axis.orientedId] = panel; - - // V1 fields - if(axis.index <= 1 && axis.v1SecondOrientedId) { - this[axis.v1SecondOrientedId + 'AxisPanel'] = panel; - } - - return panel; - } - }, - - /** - * Creates a discrete scale for a given axis. - *

- * Uses the chart's panelSizeRatio to calculate the band. - *

- * - * @param {pvc.visual.CartesianAxis} axis The axis. - * @virtual - * @type pv.Scale - */ - _createDiscreteScaleByAxis: function(axis){ - /* DOMAIN */ - - // With composite axis, only 'singleLevel' flattening works well - var dataPartValues = - axis. - dataCells. - map(function(dataCell){ return dataCell.dataPartValue; }); - - var baseData = this.visibleData(dataPartValues, {ignoreNulls: false}); - var data = baseData && baseData.flattenBy(axis.role); - - var scale = new pv.Scale.ordinal(); - if(!data || !data.count()){ - scale.isNull = true; - } else { - var values = data.children() - .select(function(child){ return def.nullyTo(child.value, ""); }) - .array(); - - scale.domain(values); - } - - return scale; - }, - - /** - * Creates a continuous time-series scale for a given axis. - * - *

- * Uses the axis' option Offset to calculate excess domain margins at each end of the scale. - *

- *

- * Also takes into account the specified axis' options - * DomainRoundMode and DesiredTickCount. - *

- * - * @param {pvc.visual.CartesianAxis} axis The axis. - * @virtual - * @type pv.Scale - */ - _createTimeSeriesScaleByAxis: function(axis){ - /* DOMAIN */ - var extent = this._getContinuousVisibleExtent(axis); // null when no data... - - var scale = new pv.Scale.linear(); - if(!extent){ - scale.isNull = true; - } else { - var dMin = extent.min; - var dMax = extent.max; - - if((dMax - dMin) === 0) { - dMax = new Date(dMax.getTime() + 3600000); // 1 h - } - - scale.domain(dMin, dMax); - scale.minLocked = extent.minLocked; - scale.maxLocked = extent.maxLocked; - } - - return scale; - }, - - /** - * Creates a continuous numeric scale for a given axis. - * - *

- * Uses the axis' option Offset to calculate excess domain margins at each end of the scale. - *

- *

- * Also takes into account the specified axis' options - * DomainRoundMode and DesiredTickCount. - *

- * - * @param {pvc.visual.CartesianAxis} axis The axis. - * @virtual - * @type pv.Scale - */ - _createNumericScaleByAxis: function(axis){ - /* DOMAIN */ - var extent = this._getContinuousVisibleExtentConstrained(axis); - - var scale = new pv.Scale.linear(); - if(!extent){ - scale.isNull = true; - } else { - var tmp; - var dMin = extent.min; - var dMax = extent.max; - - if(dMin > dMax){ - tmp = dMin; - dMin = dMax; - dMax = tmp; - } - - var originIsZero = axis.option('OriginIsZero'); - if(originIsZero){ - if(dMin === 0){ - extent.minLocked = true; - } else if(dMax === 0){ - extent.maxLocked = true; - } else if((dMin * dMax) > 0){ - /* If both negative or both positive - * the scale does not contain the number 0. - */ - if(dMin > 0){ - if(!extent.minLocked){ - extent.minLocked = true; - dMin = 0; - } - } else { - if(!extent.maxLocked){ - extent.maxLocked = true; - dMax = 0; - } - } - } - } - - /* - * If the bounds (still) are the same, things break, - * so we add a wee bit of variation. - * Ignoring locks. - */ - if(dMin > dMax){ - tmp = dMin; - dMin = dMax; - dMax = tmp; - } - - if(dMax - dMin <= 1e-12) { - if(!extent.minLocked){ - dMin = dMin !== 0 ? (dMin * 0.99) : -0.1; - } - - // If both are locked, ignore max lock - if(!extent.maxLocked || extent.minLocked){ - dMax = dMax !== 0 ? dMax * 1.01 : 0.1; - } - } - - scale.domain(dMin, dMax); - scale.minLocked = extent.minLocked; - scale.maxLocked = extent.maxLocked; - } - - return scale; - }, - - _onLaidOut: function(){ - if(this.plotPanelList && this.plotPanelList[0]){ // not the root of a multi chart - /* Set scale ranges, after layout */ - ['base', 'ortho'].forEach(function(type){ - var axes = this.axesByType[type]; - if(axes){ - axes.forEach(this._setCartAxisScaleRange, this); - } - }, this); - } - }, - - _setCartAxisScaleRange: function(axis){ - var info = this.plotPanelList[0]._layoutInfo; - var size = info.clientSize; - var length = (axis.orientation === 'x') ? - size.width : - size.height; - - axis.setScaleRange(length); - - return axis.scale; - }, - - _getAxesRoundingPaddings: function(){ - var axesPaddings = {}; - - var axesByType = this.axesByType; - ['base', 'ortho'].forEach(function(type){ - var typeAxes = axesByType[type]; - if(typeAxes){ - typeAxes.forEach(processAxis); - } - }); - - return axesPaddings; - - function setSide(side, pct, locked){ - var value = axesPaddings[side]; - if(value == null || pct > value){ - axesPaddings[side] = pct; - axesPaddings[side + 'Locked'] = locked; - } else if(locked) { - axesPaddings[side + 'Locked'] = locked; - } - } - - function processAxis(axis){ - if(axis){ - // {begin: , end: , beginLocked: , endLocked: } - var tickRoundPads = axis.getScaleRoundingPaddings(); - if(tickRoundPads){ - var isX = axis.orientation === 'x'; - setSide(isX ? 'left' : 'bottom', tickRoundPads.begin, tickRoundPads.beginLocked); - setSide(isX ? 'right' : 'top' , tickRoundPads.end, tickRoundPads.endLocked); - } - } - } - }, - - _warnSingleContinuousValueRole: function(valueRole){ - if(!valueRole.grouping.isSingleDimension) { - this._log("[WARNING] A linear scale can only be obtained for a single dimension role."); - } - - if(valueRole.grouping.isDiscrete()) { - this._log("[WARNING] The single dimension of role '{0}' should be continuous.", [valueRole.name]); - } - }, - - /** - * @virtual - */ - _getContinuousVisibleExtentConstrained: function(axis, min, max){ - var minLocked = false; - var maxLocked = false; - - if(min == null) { - min = axis.option('FixedMin'); - minLocked = (min != null); - } - - if(max == null) { - max = axis.option('FixedMax'); - maxLocked = (max != null); - } - - if(min == null || max == null) { - var baseExtent = this._getContinuousVisibleExtent(axis); // null when no data - if(!baseExtent){ - return null; - } - - if(min == null){ - min = baseExtent.min; - } - - if(max == null){ - max = baseExtent.max; - } - } - - return {min: min, max: max, minLocked: minLocked, maxLocked: maxLocked}; - }, - - /** - * Gets the extent of the values of the specified axis' roles - * over all datums of the visible data. - * - * @param {pvc.visual.CartesianAxis} valueAxis The value axis. - * @type object - * - * @protected - * @virtual - */ - _getContinuousVisibleExtent: function(valueAxis){ - - var dataCells = valueAxis.dataCells; - if(dataCells.length === 1){ - // Most common case is faster - return this._getContinuousVisibleCellExtent(valueAxis, dataCells[0]); - } - - // This implementation takes the union of - // the extents of each data cell. - // Even when a data cell has multiple data parts, - // it is evaluated as a whole. - - return def - .query(dataCells) - .select(function(dataCell){ - return this._getContinuousVisibleCellExtent(valueAxis, dataCell); - }, this) - .reduce(pvc.unionExtents, null); - }, - - /** - * Gets the extent of the values of the specified role - * over all datums of the visible data. - * - * @param {pvc.visual.CartesianAxis} valueAxis The value axis. - * @param {pvc.visual.Role} valueDataCell The data cell. - * @type object - * - * @protected - * @virtual - */ - _getContinuousVisibleCellExtent: function(valueAxis, valueDataCell){ - var valueRole = valueDataCell.role; - - this._warnSingleContinuousValueRole(valueRole); - - if(valueRole.name === 'series') { - /* not supported/implemented? */ - throw def.error.notImplemented(); - } - - var useAbs = valueAxis.scaleUsesAbs(); - var data = this.visibleData(valueDataCell.dataPartValue); - var extent = data && data - .dimensions(valueRole.firstDimensionName()) - .extent({ abs: useAbs }); - - if(extent){ - var minValue = extent.min.value; - var maxValue = extent.max.value; - return { - min: (useAbs ? Math.abs(minValue) : minValue), - max: (useAbs ? Math.abs(maxValue) : maxValue) - }; - } - }, - - markEventDefaults: { - strokeStyle: "#5BCBF5", /* Line Color */ - lineWidth: "0.5", /* Line Width */ - textStyle: "#5BCBF5", /* Text Color */ - verticalOffset: 10, /* Distance between vertical anchor and label */ - verticalAnchor: "bottom", /* Vertical anchor: top or bottom */ - horizontalAnchor: "right", /* Horizontal anchor: left or right */ - forceHorizontalAnchor: false, /* Horizontal anchor position will be respected if true */ - horizontalAnchorSwapLimit: 80 /* Horizontal anchor will switch if less than this space available */ - }, - - // TODO: chart orientation? - markEvent: function(dateString, label, options){ - - var baseScale = this.axes.base.scale; - - if(baseScale.type !== 'timeSeries'){ - this._log("Attempting to mark an event on a non timeSeries chart"); - return this; - } - - var o = $.extend({}, this.markEventDefaults, options); - - // TODO: format this using dimension formatter... - - // Are we outside the allowed scale? - var d = pv.Format.date(this.options.timeSeriesFormat).parse(dateString); - var dpos = baseScale(d), - range = baseScale.range(); - - if( dpos < range[0] || dpos > range[1]){ - this._log("Event outside the allowed range, returning"); - return this; - } - - // Add the line - - var panel = this.plotPanelList[0].pvPanel; - var h = this.yScale.range()[1]; - - // Detect where to place the horizontalAnchor - //var anchor = o.horizontalAnchor; - if( !o.forceHorizontalAnchor ){ - var availableSize = o.horizontalAnchor == "right"? range[1]- dpos : dpos; - - // TODO: Replace this availableSize condition with a check for the text size - if (availableSize < o.horizontalAnchorSwapLimit ){ - o.horizontalAnchor = o.horizontalAnchor == "right" ? "left" : "right"; - } - } - - var line = panel.add(pv.Line) - .data([0,h]) - .strokeStyle(o.strokeStyle) - .lineWidth(o.lineWidth) - .bottom(function(d){ - return d; - }) - .left(dpos); - - //var pvLabel = - line.anchor(o.horizontalAnchor) - .top(o.verticalAnchor == "top" ? o.verticalOffset : (h - o.verticalOffset)) - .add(pv.Label) - .text(label) - .textStyle(o.textStyle) - .visible(function(){ - return !this.index; - }); - - return this; - }, - - defaults: { - /* Percentage of occupied space over total space in a discrete axis band */ - panelSizeRatio: 0.9, - - // Indicates that the *base* axis is a timeseries - timeSeries: false, - timeSeriesFormat: "%Y-%m-%d" - - // Show a frame around the plot area - // plotFrameVisible: undefined - } -}); diff --git a/pacotes/ccc2/pvc/pvcCartesianAbstractPanel.js b/pacotes/ccc2/pvc/pvcCartesianAbstractPanel.js deleted file mode 100755 index 8f9b460..0000000 --- a/pacotes/ccc2/pvc/pvcCartesianAbstractPanel.js +++ /dev/null @@ -1,142 +0,0 @@ - -def -.type('pvc.CartesianAbstractPanel', pvc.PlotPanel) -.init(function(chart, parent, plot, options) { - - // Prevent the border from affecting the box model, - // providing a static 0 value, independently of the actual drawn value... - //this.borderWidth = 0; - - this.base(chart, parent, plot, options); - - var axes = this.axes; - - function addAxis(axis){ - axes[axis.type] = axis; - - // TODO: are these really needed?? - axes[axis.orientedId] = axis; - if(axis.v1SecondOrientedId){ - axes[axis.v1SecondOrientedId] = axis; - } - } - - addAxis(chart._getAxis('base', plot.option('BaseAxis' ) - 1)); - addAxis(chart._getAxis('ortho', plot.option('OrthoAxis') - 1)); - - // ---------------- - - // Initialize paddings from **chart** axes offsets - // TODO: move this to the chart?? - var pctPaddings = {}; - var hasAny = false; - - function setSide(side, pct){ - var value = pctPaddings[side]; - if(value == null || pct > value){ - hasAny = true; - pctPaddings[side] = pct; - } - } - - function processAxis(axis){ - var offset = axis && axis.option('Offset'); - if(offset != null && offset > 0 && offset < 1) { - if(axis.orientation === 'x'){ - setSide('left', offset); - setSide('right', offset); - } else { - setSide('top', offset); - setSide('bottom', offset); - } - } - } - - var chartAxes = chart.axesByType; - - ['base', 'ortho'].forEach(function(type){ - var typeAxes = chartAxes[type]; - if(typeAxes){ - typeAxes.forEach(processAxis); - } - }); - - if(hasAny){ - this.offsetPaddings = pctPaddings; - } -}) -.add({ - - offsetPaddings: null, - - _calcLayout: function(layoutInfo){ - layoutInfo.requestPaddings = this._calcRequestPaddings(layoutInfo); - }, - - _calcRequestPaddings: function(layoutInfo){ - var reqPads; - var offPads = this.offsetPaddings; - if(offPads){ - var tickRoundPads = this.chart._getAxesRoundingPaddings(); - var clientSize = layoutInfo.clientSize; - var pads = layoutInfo.paddings; - - pvc.Sides.names.forEach(function(side){ - var len_a = pvc.BasePanel.orthogonalLength[side]; - - var clientLen = clientSize[len_a]; - var paddingLen = pads[len_a]; - - var len = clientLen + paddingLen; - - // Only request offset-padding if the tickRoundPads.side is not locked - if(!tickRoundPads[side + 'Locked']){ - // Offset paddings are a percentage of the outer length - // (there are no margins in this panel). - var offLen = len * (offPads[side] || 0); - - // Rounding paddings are the percentage of the - // client length that already actually is padding - // due to domain rounding. - var roundLen = clientLen * (tickRoundPads[side] || 0); - - // So, if the user wants offLen padding but the - // client area already contains roundLen of padding, - // request only the remaining, if any. - (reqPads || (reqPads = {}))[side] = Math.max(offLen - roundLen, 0); - } - }, this); - } - - return reqPads; - }, - - /** - * @override - */ - _createCore: function() { - // Send the panel behind the axis, title and legend, panels - this.pvPanel.zOrder(-10); - - var hideOverflow; - var contentOverflow = this.chart.options.leafContentOverflow || 'auto'; - if(contentOverflow === 'auto'){ - // Overflow - hideOverflow = - def - .query(['ortho', 'base']) - .select(function(axisType) { return this.axes[axisType]; }, this) - .any(function(axis){ - return axis.option('FixedMin') != null || - axis.option('FixedMax') != null; - }); - } else { - hideOverflow = (contentOverflow === 'hidden'); - } - - if (hideOverflow){ - // Padding area is used by bubbles and other vizs without problem - this.pvPanel.borderPanel.overflow('hidden'); - } - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcCartesianGridDockingPanel.js b/pacotes/ccc2/pvc/pvcCartesianGridDockingPanel.js deleted file mode 100755 index c2b9bf0..0000000 --- a/pacotes/ccc2/pvc/pvcCartesianGridDockingPanel.js +++ /dev/null @@ -1,723 +0,0 @@ - -def -.type('pvc.CartesianGridDockingPanel', pvc.GridDockingPanel) -.init(function(chart, parent, options) { - this.base(chart, parent, options); - - this._plotBgPanel = new pvc.PlotBgPanel(chart, this); -}) -.add({ - - _getExtensionId: function(){ - return !this.chart.parent ? 'content' : 'smallContent'; - }, - - /** - * @override - */ - _createCore: function(layoutInfo){ - var chart = this.chart; - var axes = chart.axes; - var xAxis = axes.x; - var yAxis = axes.y; - - - // Full grid lines - if(xAxis.option('Visible') && xAxis.option('Grid')) { - this.xGridRule = this._createGridRule(xAxis); - } - - if(yAxis.option('Visible') && yAxis.option('Grid')) { - this.yGridRule = this._createGridRule(yAxis); - } - - this.base(layoutInfo); - - if(chart.focusWindow){ - this._createFocusWindow(layoutInfo); - } - - var plotFrameVisible; - if(chart.compatVersion() <= 1){ - plotFrameVisible = !!(xAxis.option('EndLine') || yAxis.option('EndLine')); - } else { - plotFrameVisible = def.get(chart.options, 'plotFrameVisible', true); - } - - if(plotFrameVisible) { - this.pvFrameBar = this._createFrame(layoutInfo, axes); - } - - if(xAxis.scaleType !== 'discrete' && xAxis.option('ZeroLine')) { - this.xZeroLine = this._createZeroLine(xAxis, layoutInfo); - } - - if(yAxis.scaleType !== 'discrete' && yAxis.option('ZeroLine')) { - this.yZeroLine = this._createZeroLine(yAxis, layoutInfo); - } - }, - - _createGridRule: function(axis){ - var scale = axis.scale; - if(scale.isNull){ - return; - } - - // Composite axis don't fill ticks - var isDiscrete = axis.role.grouping.isDiscrete(); - var axisPanel = this.chart.axesPanels[axis.id]; - var rootScene = axisPanel._getRootScene(); - if(!rootScene){ - return; - } - - var margins = this._layoutInfo.gridMargins; - var paddings = this._layoutInfo.gridPaddings; - - var tick_a = axis.orientation === 'x' ? 'left' : 'bottom'; - var len_a = this.anchorLength(tick_a); - var obeg_a = this.anchorOrtho(tick_a); - var oend_a = this.anchorOpposite(obeg_a); - - var tick_offset = margins[tick_a] + paddings[tick_a]; - - var obeg = margins[obeg_a]; - var oend = margins[oend_a]; - -// TODO: Implement GridCrossesMargin ... -// var orthoAxis = this._getOrthoAxis(axis.type); -// if(!orthoAxis.option('GridCrossesMargin')){ -// obeg += paddings[obeg_a]; -// oend += paddings[oend_a]; -// } - - var tickScenes = rootScene.leafs().array(); - var tickCount = tickScenes.length; - if(isDiscrete && tickCount){ - // Grid rules are generated for MAJOR ticks only. - // For discrete axes, each category - // has a grid line at the beginning of the band, - // and an extra end line in the last band - tickScenes.push(tickScenes[tickCount - 1]); - } - - var wrapper; - if(this.compatVersion() <= 1){ - wrapper = function(v1f){ - return function(tickScene){ - return v1f.call(this, tickScene.vars.tick.rawValue); - }; - }; - } - - var pvGridRule = new pvc.visual.Rule(this, this.pvPanel, { - extensionId: axis.extensionPrefixes.map(function(prefix){ return prefix + 'Grid'; }), - wrapper: wrapper - }) - .lock('data', tickScenes) - .lock(len_a, null) - .override('defaultColor', function(){ - return pv.color("#f0f0f0"); - }) - .pvMark - .lineWidth(1) - .antialias(true) - [obeg_a](obeg) - [oend_a](oend) - .zOrder(-12) - .events('none') - ; - - if(isDiscrete){ - var halfStep = scale.range().step / 2; - pvGridRule - .lock(tick_a, function(tickScene){ - var tickPosition = tick_offset + scale(tickScene.vars.tick.value); - - // Use **pvMark** index, cause the last two scenes report the same index. - var isLastLine = this.index === tickCount; - - return tickPosition + (isLastLine ? halfStep : -halfStep); - }) - ; - } else { - pvGridRule - .lock(tick_a, function(tickScene){ - return tick_offset + scale(tickScene.vars.tick.value); - }); - } - - return pvGridRule; - }, - - /* zOrder - * - * TOP - * ------------------- - * Axis Rules: 0 - * Line/Dot/Area Content: -7 - * Frame/EndLine: -8 - * ZeroLine: -9 <<------ - * Content: -10 (default) - * Grid: -12 - * ------------------- - * BOT - */ - - _createFrame: function(layoutInfo, axes){ - if(axes.base.scale.isNull || - (axes.ortho.scale.isNull && (!axes.ortho2 || axes.ortho2.scale.isNull))){ - return; - } - - var margins = layoutInfo.gridMargins; - var left = margins.left; - var right = margins.right; - var top = margins.top; - var bottom = margins.bottom; - - // TODO: Implement GridCrossesMargin ... - // Need to find the correct bounding box. - // xScale(xScale.domain()[0]) -> xScale(xScale.domain()[1]) - // and - // yScale(yScale.domain()[0]) -> yScale(yScale.domain()[1]) - var extensionIds = []; - if(this.compatVersion() <= 1){ - extensionIds.push('xAxisEndLine'); - extensionIds.push('yAxisEndLine'); - } - - extensionIds.push('plotFrame'); - - return new pvc.visual.Panel(this, this.pvPanel, { - extensionId: extensionIds - }) - .pvMark - .lock('left', left) - .lock('right', right) - .lock('top', top) - .lock('bottom', bottom) - .lock('fillStyle', null) - .events('none') - .strokeStyle("#666666") - .lineWidth(1) - .antialias(false) - .zOrder(-8) - ; - }, - - _createZeroLine: function(axis, layoutInfo){ - var scale = axis.scale; - if(!scale.isNull){ - var domain = scale.domain(); - - // Domain crosses zero? - if(domain[0] * domain[1] < -1e-12){ - // TODO: Implement GridCrossesMargin ... - - var a = axis.orientation === 'x' ? 'left' : 'bottom'; - var len_a = this.anchorLength(a); - var obeg_a = this.anchorOrtho(a); - var oend_a = this.anchorOpposite(obeg_a); - - var margins = layoutInfo.gridMargins; - var paddings = layoutInfo.gridPaddings; - - var zeroPosition = margins[a] + paddings[a] + scale(0); - - var obeg = margins[obeg_a]; - var oend = margins[oend_a]; - - var rootScene = new pvc.visual.Scene(null, { - panel: this - }); - - return new pvc.visual.Rule(this, this.pvPanel, { - extensionId: axis.extensionPrefixes.map(function(prefix){ return prefix + 'ZeroLine'; }) - }) - .lock('data', [rootScene]) - .lock(len_a, null) - .lock(obeg_a, obeg) - .lock(oend_a, oend) - .lock(a, zeroPosition) - .override('defaultColor', function(){ - return pv.color("#666666"); - }) - .pvMark - .events('none') - .lineWidth(1) - .antialias(true) - .zOrder(-9) - ; - } - } - }, - - _createFocusWindow: function(layoutInfo){ - var me = this; - var topRoot = me.topRoot; - var chart = me.chart; - - var focusWindow = chart.focusWindow.base; - - var axis = focusWindow.axis; - var scale = axis.scale; - if(scale.isNull){ - return; - } - - var resizable = focusWindow.option('Resizable'); - var movable = focusWindow.option('Movable' ); - var isDiscrete = axis.isDiscrete(); - - var isV = chart.isOrientationVertical(); - var a_left = isV ? 'left' : 'top'; - var a_top = isV ? 'top' : 'left'; - var a_width = me.anchorOrthoLength(a_left); - var a_right = me.anchorOpposite(a_left); - var a_height= me.anchorOrthoLength(a_top); - var a_bottom= me.anchorOpposite(a_top); - var a_x = isV ? 'x' : 'y'; - var a_dx = 'd' + a_x; - var a_y = isV ? 'y' : 'x'; - var a_dy = 'd' + a_y; - - var margins = layoutInfo.gridMargins; - var paddings = layoutInfo.gridPaddings; - - var space = { - left: margins.left + paddings.left, - right: margins.right + paddings.right, - top: margins.top + paddings.top, - bottom: margins.bottom + paddings.bottom - }; - - space.width = space.left + space.right; - space.height = space.top + space.bottom; - - var clientSize = layoutInfo.clientSize; - - var wf = clientSize[a_width ]; - var hf = clientSize[a_height]; - - // Child plot's client size - var w = wf - space[a_width ]; - var h = hf - space[a_height]; - - var padLeft = paddings[a_left ]; - var padRight = paddings[a_right]; - - // ----------------- - - var scene = new pvc.visual.Scene(null, {panel: this}); - - // Initialize x,y,dx and dy properties from focusWindow - var band = isDiscrete ? scale.range().step : 0; - var halfBand = band/2; - - scene[a_x] = scale(focusWindow.begin) - halfBand, - - // Add band for an inclusive discrete end - scene[a_dx] = band + (scale(focusWindow.end) - halfBand) - scene[a_x], - - resetSceneY(); - - function resetSceneY(){ - scene[a_y ] = 0 - paddings[a_top ]; - scene[a_dy] = h + paddings[a_top] + paddings[a_bottom]; - } - - // ----------------- - - var sceneProp = function(p){ - return function(){ return scene[p]; }; - }; - - var boundLeft = function(){ - var begin = scene[a_x]; - return Math.max(0, Math.min(w, begin)); - }; - - var boundWidth = function(){ - var begin = boundLeft(); - var end = scene[a_x] + scene[a_dx]; - end = Math.max(0, Math.min(w, end)); - return end - begin; - }; - - var addSelBox = function(panel, id){ - return new pvc.visual.Bar(me, panel, { - extensionId: id, - normalStroke: true, - noHover: true, - noSelect: true, - noClick: true, - noDoubleClick: true, - noTooltip: true, - showsInteraction: false - }) - //.override('defaultStrokeWidth', function( ){ return 0; }) - .pvMark - .lock('data') - .lock('visible') - .lock(a_left, boundLeft ) - .lock(a_width, boundWidth) - .lock(a_top, sceneProp(a_y )) - .lock(a_height, sceneProp(a_dy)) - .lock(a_bottom) - .lock(a_right ) - .sign - ; - }; - - // BACKGROUND - var baseBgPanel = this._plotBgPanel.pvPanel.borderPanel; - baseBgPanel - .lock('data', [scene]) - ; - - if(movable && resizable){ // cannot activate resizable while we can't guarantee that it respects length - // Allow creating a new focus area. - // Works when "dragging" on the courtains area, - // (if inside the paddings area). - baseBgPanel.paddingPanel - .lock('events', 'all') - .lock('cursor', 'crosshair') - .event('mousedown', - pv.Behavior.select() - .autoRender(false) - .collapse(isV ? 'y' : 'x') - //.preserveLength(!resizable) - .positionConstraint(function(drag){ - var op = drag.phase ==='start' ? - 'new' : - 'resize-end'; - return positionConstraint(drag, op); - })) - .event('selectstart', function(ev){ - // reset the scene's orthogonal props - resetSceneY(); - - // Redraw on mouse down. - onDrag(ev); - }) - .event('select', onDrag) - .event('selectend', onDrag) - ; - } else { - baseBgPanel.paddingPanel - .events('all') - ; - } - - // This panel serves mainly to enable dragging of the focus area, - // and possibly, for bg coloring. - // The drag action is only available when there aren't visual elements - // in the front. This allows to keep elements interactive. - var focusBg = addSelBox(baseBgPanel.paddingPanel, 'focusWindowBg') - .override('defaultColor', function(type){ - return pvc.invisibleFill; - }) - .pvMark - ; - - if(movable){ - focusBg - .lock('events', 'all' ) - .lock('cursor', 'move') - .event("mousedown", - pv.Behavior.drag() - .autoRender(false) - .collapse(isV ? 'y' : 'x') - .positionConstraint(function(drag){ - positionConstraint(drag, 'move'); - })) - .event("drag", onDrag) - .event("dragend", onDrag) - ; - } else { - focusBg.events('none'); - } - - // -------------------------------------- - // FOREGROUND - - // Coordinate system like that of the plots. - // X and Y scales can be used on this. - var baseFgPanel = new pvc.visual.Panel(me, me.pvPanel) - .pvMark - .lock('data', [scene]) - .lock('visible') - .lock('fillStyle', pvc.invisibleFill) - .lock('left', space.left ) - .lock('right', space.right ) - .lock('top', space.top ) - .lock('bottom', space.bottom) - .lock('zOrder', 10) // above axis rules - /* Use the panel to show a steady cursor while moving/resizing, - * by receiving all events. - * The drag continues to live because it listens to the - * root's mousemove/up and we're not cancelling the events. - * Visual elements do not receive the events because - * they're in a sibling panel. - */ - .lock('events', function(){ - var drag = scene.drag; - return drag && drag.phase !== 'end' ? 'all' : 'none'; - }) - .lock('cursor', function(){ - var drag = scene.drag; - return drag && drag.phase !== 'end' ? - ((drag.type === 'drag' || (drag.type === 'select' && !resizable)) ? - 'move' : - (isV ? 'ew-resize' : 'ns-resize')) : null; - }) - .antialias(false) - ; - - // FG BASE CURTAIN - var curtainFillColor = 'rgba(20, 20, 20, 0.1)'; - - new pvc.visual.Bar(me, baseFgPanel, { - extensionId: 'focusWindowBaseCurtain', - normalStroke: true, - noHover: true, - noSelect: true, - noClick: true, - noDoubleClick: true, - noTooltip: true, - showsInteraction: false - }) - .override('defaultColor', function(type){ - return type === 'stroke' ? null : curtainFillColor; - }) - .pvMark - .lock('data', [scene, scene]) - .lock('visible') - .lock('events', 'none') - .lock(a_left, function(){ return !this.index ? -padLeft : boundLeft() + boundWidth(); }) - .lock(a_right, function(){ return !this.index ? null : -padRight; }) - .lock(a_width, function(){ return !this.index ? padLeft + boundLeft() : null; }) - .lock(a_top, sceneProp(a_y )) - .lock(a_height, sceneProp(a_dy)) - .lock(a_bottom) - ; - - // FG FOCUS BOX - // for coloring and anchoring - var selectBoxFg = addSelBox(baseFgPanel, 'focusWindow') - .override('defaultColor', function(type){ return null; }) - .pvMark - .lock('events', 'none') - ; - - // FG BOUNDARY/RESIZE GRIP - var addResizeSideGrip = function(side){ - // TODO: reversed scale?? - var a_begin = (side === 'left' || side === 'top') ? 'begin' : 'end'; - - var opposite = me.anchorOpposite(side); - var fillColor = 'linear-gradient(to ' + opposite + ', ' + curtainFillColor + ', #444 90%)'; - var grip = new pvc.visual.Bar(me, selectBoxFg.anchor(side), { - extensionId: focusWindow.id + 'Grip' + def.firstUpperCase(a_begin), - normalStroke: true, - noHover: true, - noSelect: true, - noClick: true, - noDoubleClick: true, - noTooltip: true, - showsInteraction: false - }) - .override('defaultColor', function(type){ - return type === 'stroke' ? null : fillColor; - }) - .pvMark - .lock('data') - .lock('visible') - [a_top ](scene[a_y ]) - [a_height](scene[a_dy]) - ; - - if(resizable){ - var opId = 'resize-' + a_begin; - grip - .lock('events', 'all') - [a_width](5) - .cursor(isV ? 'ew-resize' : 'ns-resize') - .event("mousedown", - pv.Behavior.resize(side) - .autoRender(false) - .positionConstraint(function(drag){ - positionConstraint(drag, opId); - }) - .preserveOrtho(true)) - .event("resize", onDrag) - .event("resizeend", onDrag) - ; - } else { - grip - .events('none') - [a_width](1) - ; - } - - return grip; - }; - - addResizeSideGrip(a_left ); - addResizeSideGrip(a_right); - - // -------------------- - - function onDrag(){ - var ev = arguments[arguments.length - 1]; - var isEnd = ev.drag.phase === 'end'; - - // Prevent tooltips and hovers - topRoot._isRubberBandSelecting = !isEnd; - - baseBgPanel.render(); - baseFgPanel.render(); - - - var pbeg = scene[a_x]; - var pend = scene[a_x] + scene[a_dx]; - if(!isV){ - // from bottom, instead of top... - var temp = w - pbeg; - pbeg = w - pend; - pend = temp; - } - - focusWindow._updatePosition(pbeg, pend, /*select*/ isEnd, /*render*/ true); - } - - // ---------------- - var a_p = a_x; - var a_dp = a_dx; - - function positionConstraint(drag, op){ - // Never called on drag.phase === 'end' - var m = drag.m; - - // Only constraining the base position - var p = m[a_p]; - var b, e, l; - var l0 = scene[a_dp]; - - var target; - switch(op){ - case 'new': - l = 0; - target = 'begin'; - break; - - case 'resize-begin': - l = l0; - target = 'begin'; - break; - - case 'move': - l = l0; - target = 'begin'; - break; - - case 'resize-end': // use on Select and Resize - l = p - scene[a_p]; - target = 'end'; - break; - } - - var min = drag.min[a_p]; - var max = drag.max[a_p]; - - var oper = { - type: op, - target: target, - point: p, - length: l, // new length - length0: l0, // prev length - min: min, - max: max, - minView: 0, - maxView: w - }; - - focusWindow._constraintPosition(oper); - - // Sync - m[a_p] = oper.point; - - // TODO: not working on horizontal orientation??? - // Overwrite min or max on resize - switch(op){ - case 'resize-begin': - // The maximum position is the end grip - oper.max = Math.min(oper.max, scene[a_p] + scene[a_dp]); - break; - - case 'resize-end': - // The minimum position is the begin grip - oper.min = Math.max(oper.min, scene[a_p]); - break; - } - - drag.min[a_p] = oper.min; - drag.max[a_p] = oper.max; - } - }, - - _getOrthoAxis: function(type){ - var orthoType = type === 'base' ? 'ortho' : 'base'; - return this.chart.axes[orthoType]; - }, - - /* - * @override - */ - _getDatumsOnRect: function(datumMap, rect, keyArgs){ - // TODO: this is done for x and y axis only, which is ok for now, - // as only discrete axes use selection and - // multiple axis are only continuous... - var chart = this.chart, - xAxisPanel = chart.axesPanels.x, - yAxisPanel = chart.axesPanels.y, - xDatumMap, - yDatumMap; - - //1) x axis - if(xAxisPanel){ - xDatumMap = new def.Map(); - xAxisPanel._getDatumsOnRect(xDatumMap, rect, keyArgs); - if(!xDatumMap.count) { - xDatumMap = null; - } - } - - //2) y axis - if(yAxisPanel){ - yDatumMap = new def.Map(); - yAxisPanel._getOwnDatumsOnRect(yDatumMap, rect, keyArgs); - if(!yDatumMap.count) { - yDatumMap = null; - } - } - - // Rubber band selects on both axes? - if(xDatumMap && yDatumMap) { - xDatumMap.intersect(yDatumMap, /* into */ datumMap); - - keyArgs.toggle = true; - - // Rubber band selects over any of the axes? - } else if(xDatumMap) { - datumMap.copy(xDatumMap); - } else if(yDatumMap) { - datumMap.copy(yDatumMap); - } else { - chart.plotPanelList.forEach(function(plotPanel){ - plotPanel._getDatumsOnRect(datumMap, rect, keyArgs); - }, this); - } - } -}); diff --git a/pacotes/ccc2/pvc/pvcCategoricalAbstract.js b/pacotes/ccc2/pvc/pvcCategoricalAbstract.js deleted file mode 100755 index 201a54d..0000000 --- a/pacotes/ccc2/pvc/pvcCategoricalAbstract.js +++ /dev/null @@ -1,446 +0,0 @@ -/** - * CategoricalAbstract is the base class for all categorical or timeseries - */ -def -.type('pvc.CategoricalAbstract', pvc.CartesianAbstract) -.init(function(options){ - - this.base(options); - - var parent = this.parent; - if(parent) { - this._catRole = parent._catRole; - } -}) -.add({ - /** - * Initializes each chart's specific roles. - * @override - */ - _initVisualRoles: function(){ - - this.base(); - - this._catRole = this._addVisualRole('category', this._getCategoryRoleSpec()); - }, - - _getCategoryRoleSpec: function(){ - return { - isRequired: true, - defaultDimension: 'category*', - autoCreateDimension: true - }; - }, - - _generateTrendsDataCellCore: function(newDatums, dataCell, trendInfo){ - var serRole = this._serRole; - var xRole = this._catRole; - var yRole = dataCell.role; - var trendOptions = dataCell.trend; - - this._warnSingleContinuousValueRole(yRole); - - var dataPartDimName = this._dataPartRole.firstDimensionName(); - var yDimName = yRole.firstDimensionName(); - var xDimName; - var isXDiscrete = xRole.isDiscrete(); - if(!isXDiscrete){ - xDimName = xRole.firstDimensionName(); - } - - var sumKeyArgs = { zeroIfNone: false }; - var ignoreNullsKeyArgs = {ignoreNulls: false}; - - // Visible data grouped by category and then series - var data = this.visibleData(dataCell.dataPartValue); - - // TODO: It is usually the case, but not certain, that the base axis' - // dataCell(s) span "all" data parts. - // The data that will be shown in the base scale... - // Ideally the base scale would already be set up... - var allPartsData = this.visibleData(null, ignoreNullsKeyArgs); - var allCatDataRoot = allPartsData.flattenBy(xRole, ignoreNullsKeyArgs); - var allCatDatas = allCatDataRoot._children; - - // For each series... - def - .scope(function(){ - return (serRole && serRole.isBound()) ? - data.flattenBy(serRole).children() : // data already only contains visible data - def.query([null]) // null series - ; - }) - .each(genSeriesTrend, this); - - function genSeriesTrend(serData1){ - var funX = isXDiscrete ? - null : // means: "use *index* as X value" - function(allCatData){ - return allCatData.atoms[xDimName].value; - }; - - var funY = function(allCatData){ - var group = data._childrenByKey[allCatData.key]; - if(group && serData1){ - group = group._childrenByKey[serData1.key]; - } - - // When null, the data point ends up being ignored - return group ? group.dimensions(yDimName).sum(sumKeyArgs) : null; - }; - - var options = def.create(trendOptions, { - rows: def.query(allCatDatas), - x: funX, - y: funY - }); - - var trendModel = trendInfo.model(options); - - // If a label has already been registered, it is preserved... (See BaseChart#_fixTrendsLabel) - var dataPartAtom = data.owner - .dimensions(dataPartDimName) - .intern(this.root._firstTrendAtomProto); - - if(trendModel){ - // At least one point... - // Sample the line on each x and create a datum for it - // on the 'trend' data part - allCatDatas.forEach(function(allCatData, index){ - var trendX = isXDiscrete ? - index : - allCatData.atoms[xDimName].value; - - var trendY = trendModel.sample(trendX, funY(allCatData), index); - if(trendY != null){ - var catData = data._childrenByKey[allCatData.key]; - var efCatData = catData || allCatData; - - var atoms; - if(serData1){ - var catSerData = catData && - catData._childrenByKey[serData1.key]; - - if(catSerData){ - atoms = Object.create(catSerData._datums[0].atoms); - } else { - // Missing data point - atoms = Object.create(efCatData._datums[0].atoms); - - // Now copy series atoms - def.copyOwn(atoms, serData1.atoms); - } - } else { - // Series is unbound - atoms = Object.create(efCatData._datums[0].atoms); - } - - atoms[yDimName] = trendY; - atoms[dataPartDimName] = dataPartAtom; - - var newDatum = new pvc.data.Datum(efCatData.owner, atoms); - newDatum.isVirtual = true; - newDatum.isTrend = true; - newDatum.trendType = trendInfo.type; - - newDatums.push(newDatum); - } - }, this); - } - } - }, - - _interpolateDataCell: function(dataCell){ - var nullInterpMode = dataCell.nullInterpolationMode; - if(nullInterpMode){ - var InterpType; - switch(dataCell.nullInterpolationMode){ - case 'linear': InterpType = pvc.data.LinearInterpolationOper; break; - case 'zero': InterpType = pvc.data.ZeroInterpolationOper; break; - case 'none': break; - default: throw def.error.argumentInvalid('nullInterpolationMode', '' + nullInterpMode); - } - - if(InterpType){ - this._warnSingleContinuousValueRole(dataCell.role); - - // TODO: It is usually the case, but not certain, that the base axis' - // dataCell(s) span "all" data parts. - var visibleData = this.visibleData(dataCell.dataPartValue); - if(visibleData.childCount() > 0){ - var allPartsData = this.visibleData(null, {ignoreNulls: false}); - new InterpType( - allPartsData, - visibleData, - this._catRole, - this._serRole, - dataCell.role, - true) // dataCell.isStacked - .interpolate(); - } - } - } - }, - - /** - * @override - */ - _createVisibleData: function(dataPartValue, keyArgs){ - var serGrouping = this._serRole && this._serRole.flattenedGrouping(); - var catGrouping = this._catRole.flattenedGrouping(); - var partData = this.partData(dataPartValue); - - var ignoreNulls = def.get(keyArgs, 'ignoreNulls'); - - // Allow for more caching when isNull is null - var groupKeyArgs = { visible: true, isNull: ignoreNulls ? false : null}; - - return serGrouping ? - // <=> One multi-dimensional, two-levels data grouping - partData.groupBy([catGrouping, serGrouping], groupKeyArgs) : - partData.groupBy(catGrouping, groupKeyArgs); - }, - - /** - * Obtains the extent of the specified value axis' role - * and data part values. - * - *

- * Takes into account that values are shown grouped per category. - *

- * - *

- * The fact that values are stacked or not, per category, - * is also taken into account. - * Each data part can have its own stacking. - *

- * - *

- * When more than one datum exists per series and category, - * the sum of its values is considered. - *

- * - * @param {pvc.visual.CartesianAxis} valueAxis The value axis. - * @param {pvc.visual.Role} valueDataCell The data cell. - * @type object - * - * @override - */ - _getContinuousVisibleCellExtent: function(valueAxis, valueDataCell){ - var valueRole = valueDataCell.role; - - switch(valueRole.name){ - case 'series':// (series throws in base) - case 'category': - /* Special case. - * The category role's single dimension belongs to the grouping dimensions of data. - * As such, the default method is adequate - * (gets the extent of the value dim on visible data). - * - * Continuous baseScale's, like timeSeries go this way. - */ - return this.base(valueAxis, valueDataCell); - } - - this._warnSingleContinuousValueRole(valueRole); - - var dataPartValue = valueDataCell.dataPartValue; - var valueDimName = valueRole.firstDimensionName(); - var data = this.visibleData(dataPartValue); - var useAbs = valueAxis.scaleUsesAbs(); - - if(valueAxis.type !== 'ortho' || !valueDataCell.isStacked){ - return data.leafs() - .select(function(serGroup){ - var value = serGroup.dimensions(valueDimName).sum(); - return useAbs && value < 0 ? -value : value; - }) - .range(); - } - - /* - * data is grouped by category and then by series - * So direct childs of data are category groups - */ - return data.children() - /* Obtain the value extent of each category */ - .select(function(catGroup){ - var range = this._getStackedCategoryValueExtent(catGroup, valueDimName, useAbs); - if(range){ - return {range: range, group: catGroup}; - } - }, this) - .where(def.notNully) - - /* Combine the value extents of all categories */ - .reduce(function(result, rangeInfo){ - return this._reduceStackedCategoryValueExtent( - result, - rangeInfo.range, - rangeInfo.group); - }.bind(this), null); - -// The following would not work: -// var max = data.children() -// .select(function(catGroup){ return catGroup.dimensions(valueDimName).sum(); }) -// .max(); -// -// return max != null ? {min: 0, max: max} : null; - }, - - /** - * Obtains the extent of a value dimension in a given category group. - * The default implementation determines the extent by separately - * summing negative and positive values. - * Supports {@link #_getContinuousVisibleExtent}. - */ - _getStackedCategoryValueExtent: function(catGroup, valueDimName, useAbs){ - var posSum = null, - negSum = null; - - catGroup - .children() - /* Sum all datum's values on the same leaf */ - .select(function(serGroup){ - var value = serGroup.dimensions(valueDimName).sum(); - return useAbs && value < 0 ? -value : value; - }) - /* Add to positive or negative totals */ - .each(function(value){ - // Note: +null === 0 - if(value != null){ - if(value >= 0){ - posSum += value; - } else { - negSum += value; - } - } - }); - - if(posSum == null && negSum == null){ - return null; - } - - return {max: posSum || 0, min: negSum || 0}; - }, - - /** - * Reduce operation of category ranges, into a global range. - * - * The default implementation performs a range "union" operation. - * - * Supports {@link #_getContinuousVisibleExtent}. - */ - _reduceStackedCategoryValueExtent: function(result, catRange, catGroup){ - return pvc.unionExtents(result, catRange); - }, - - _coordinateSmallChartsLayout: function(scopesByType){ - // TODO: optimize the case were - // the title panels have a fixed size and - // the x and y FixedMin and FixedMax are all specified... - // Don't need to coordinate in that case. - - this.base(scopesByType); - - // Force layout and retrieve sizes of - // * title panel - // * y panel if column or global scope (column scope coordinates x scales, but then the other axis' size also affects the layout...) - // * x panel if row or global scope - var titleSizeMax = 0; - var titleOrthoLen; - - var axisIds = null; - var sizesMaxByAxisId = {}; // {id: {axis: axisSizeMax, title: titleSizeMax} } - - // Calculate maximum sizes - this.children.forEach(function(childChart){ - - childChart.basePanel.layout(); - - var size; - var panel = childChart.titlePanel; - if(panel){ - if(!titleOrthoLen){ - titleOrthoLen = panel.anchorOrthoLength(); - } - - size = panel[titleOrthoLen]; - if(size > titleSizeMax){ - titleSizeMax = size; - } - } - - // ------ - - var axesPanels = childChart.axesPanels; - if(!axisIds){ - axisIds = - def - .query(def.ownKeys(axesPanels)) - .where(function(alias){ - return alias === axesPanels[alias].axis.id; - }) - .select(function(id){ - // side effect - sizesMaxByAxisId[id] = {axis: 0, title: 0}; - return id; - }) - .array(); - } - - axisIds.forEach(function(id){ - var axisPanel = axesPanels[id]; - var sizes = sizesMaxByAxisId[id]; - - var ol = axisPanel.axis.orientation === 'x' ? 'height' : 'width'; - size = axisPanel[ol]; - if(size > sizes.axis){ - sizes.axis = size; - } - - var titlePanel = axisPanel.titlePanel; - if(titlePanel){ - size = titlePanel[ol]; - if(size > sizes.title){ - sizes.title = size; - } - } - }); - }, this); - - // Apply the maximum sizes to the corresponding panels - this.children.forEach(function(childChart){ - - if(titleSizeMax > 0){ - var panel = childChart.titlePanel; - panel.size = panel.size.clone().set(titleOrthoLen, titleSizeMax); - } - - // ------ - - var axesPanels = childChart.axesPanels; - axisIds.forEach(function(id){ - var axisPanel = axesPanels[id]; - var sizes = sizesMaxByAxisId[id]; - - var ol = axisPanel.axis.orientation === 'x' ? 'height' : 'width'; - axisPanel.size = axisPanel.size.clone().set(ol, sizes.axis); - - var titlePanel = axisPanel.titlePanel; - if(titlePanel){ - titlePanel.size = titlePanel.size.clone().set(ol, sizes.title); - } - }); - - // Invalidate their previous layout - childChart.basePanel.invalidateLayout(); - }, this); - }, - - defaults: { - // Ortho <- value role - // TODO: this should go somewhere else - orthoAxisOrdinal: false // when true => ortho axis gets the series role (instead of the value role) - } -}); diff --git a/pacotes/ccc2/pvc/pvcCategoricalAbstractPanel.js b/pacotes/ccc2/pvc/pvcCategoricalAbstractPanel.js deleted file mode 100755 index cece2f7..0000000 --- a/pacotes/ccc2/pvc/pvcCategoricalAbstractPanel.js +++ /dev/null @@ -1,9 +0,0 @@ - -def -.type('pvc.CategoricalAbstractPanel', pvc.CartesianAbstractPanel) -.init(function(chart, parent, plot, options){ - - this.base(chart, parent, plot, options); - - this.stacked = plot.option('Stacked'); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcDataTree.js b/pacotes/ccc2/pvc/pvcDataTree.js deleted file mode 100755 index ea980c4..0000000 --- a/pacotes/ccc2/pvc/pvcDataTree.js +++ /dev/null @@ -1,718 +0,0 @@ - -/** - * DataTree visualises a data-tree (also called driver tree). - * It uses a data-sources to obtain the definition of data tree. - * Each node of the tree can have it's own datasource to visualize the - * node. - */ -def -.type('pvc.DataTree', pvc.BaseChart) -.init(function(options){ - // Force the value dimension not to be a number - options = options || {}; - options.dimensionGroups = options.dimensionGroups || {}; - if(!options.dimensionGroups.value) { - options.dimensionGroups.value = {valueType: null}; - } - - this.base(options); -}) -.add({ - - // the structure of the dataTree is provided by a separate datasource - structEngine: null, - structMetadata: null, - structDataset: null, - - DataTreePanel : null, - - _getColorRoleSpec: function(){ - return { isRequired: true, defaultSourceRole: 'category', requireIsDiscrete: true }; - }, - - setStructData: function(data){ - this.structDataset = data.resultset; - if (!this.structDataset.length){ - this._log("Warning: Structure-dataset is empty"); - } - - this.structMetadata = data.metadata; - if (!this.structMetadata.length){ - this._log("Warning: Structure-Metadata is empty"); - } - }, - - _preRenderContent: function(contentOptions){ - // Create DataEngine - var structEngine = this.structEngine; - var structType = structEngine ? structEngine.type : new pvc.data.ComplexType(); - // Force the value dimension not to be a number - structType.addDimension('value', {}); - - var translOptions = { - seriesInRows: true, - crosstabMode: true - }; - - var translation = new pvc.data.CrosstabTranslationOper(structType, this.structDataset, this.structMetadata, translOptions); - translation.configureType(); - if(!structEngine) { - structEngine = this.structEngine = new pvc.data.Data({type: structType}); - } - - structEngine.load(translation.execute(structEngine)); - - if(pvc.debug >= 3){ - this._log(this.structEngine.getInfo()); - } - - // ------------------ - - this.dataTreePanel = new pvc.DataTreePanel(this, this.basePanel, def.create(contentOptions, { - topRuleOffset : this.options.topRuleOffset, - botRuleOffset : this.options.botRuleOffset, - leftRuleOffset : this.options.leftRuleOffset, - rightRuleOffset : this.options.rightRuleOffset, - boxplotColor: this.options.boxplotColor, - valueFontsize: this.options.valueFontsize, - headerFontsize: this.options.headerFontsize, - border: this.options.border, - perpConnector: this.options.perpConnector, - numDigits: this.options.numDigits, - minVerticalSpace: this.options.minVerticalSpace, - connectorSpace: this.options.connectorSpace, - minAspectRatio: this.options.minAspectRatio - })); - }, - - defaults: { - compatVersion: 1, - - // margins around the full tree - topRuleOffset: 30, - botRuleOffset: 30, - leftRuleOffset: 60, - rightRuleOffset: 60, - // box related parameters - boxplotColor: "grey", - headerFontsize: 16, - valueFontsize: 20, - border: 2, // bordersize in pixels - // use perpendicular connector lines between boxes. - perpConnector: false, - // number of digits (after dot for labels) - numDigits: 0, - // the space for the connectors is 15% of the width of a grid cell - connectorSpace: 0.15, - // the vertical space between gridcells is at least 5% - minVerticalSpace: 0.05, - // aspect ratio = width/height (used to limit AR of the boxes) - minAspectRatio: 2.0 - - //selectParam: undefined - } -}); - -/* - * DataTree chart panel. - * << to be filled out >> - * - * Has the following protovis extension points: - * - * chart_ - for the main chart Panel - * << to be filled out >> - */ -def -.type('pvc.DataTreePanel', pvc.PlotPanel) -.add({ - - pvDataTree: null, - - treeElements: null, - - structMap: null, - structArr: null, - - hRules: null, - vRules: null, - rules: null, - - // generating Perpendicular connectors - // (only using horizontal and vertical rules) - // leftLength gives the distance from the left box to the - // splitting point of the connector - generatePerpConnectors: function(leftLength) { - - this.hRules = []; - this.vRules = []; - this.rules = []; // also initialize this rule-set - - for(var e in this.structMap) { - var elem = this.structMap[e]; - if (elem.children != null) { - var min = +10000, max = -10000; - var theLeft = elem.left + elem.width; - this.hRules.push({"left": theLeft, - "width": leftLength, - "bottom": elem.bottom + elem.height/2}); - theLeft += leftLength; - for(var i in elem.children) { - var child = this.structMap[ elem.children[i] ]; - var theBottom = child.bottom + child.height/2; - if (theBottom > max) { max = theBottom; } - if (theBottom < min) { min = theBottom; } - this.hRules.push({"left": theLeft, - "width": child.left - theLeft, - "bottom": theBottom}); - } - - // a vertical rule is only added when needed - if (max > min) { - this.vRules.push({"left": theLeft, - "bottom": min, - "height": max - min}); - } - } - } - }, - - // generate a line segment and add it to rules - generateLineSegment: function(x1, y1, x2, y2) { - var line = []; - line.push({"x": x1, - "y": y1}); - line.push({"x": x2, - "y": y2}); - this.rules.push(line); - }, - - // leftLength gives the distance from the left box to the - // splitting point of the connector - generateConnectors: function(leftLength) { - - this.hRules = []; - this.vRules = []; - - if (this.chart.options.perpConnector) { - this.generatePerpConnectors(leftLength); - return; - } - - // this time were using diagonal rules - this.rules = []; - - for(var e in this.structMap) { - var elem = this.structMap[e]; - if (elem.children != null) { - var theCenter, child, i; - - // compute the mid-point - var min = +10000, max = -10000; - for(i in elem.children) { - child = this.structMap[ elem.children[i] ]; - theCenter = child.bottom + child.height/2; - if (theCenter > max) { max = theCenter; } - if (theCenter < min) { min = theCenter; } - } - var mid = (max + min)/2; - - var theLeft1 = elem.left + elem.width; - var theLeft2 = theLeft1 + leftLength; - - // outbound line of the left-hand box - this.generateLineSegment(theLeft1, elem.bottom + elem.height/2, - theLeft2, mid); - - // incoming lines of the right-hand boxes - for(i in elem.children) { - child = this.structMap[ elem.children[i] ]; - theCenter = child.bottom + child.height/2; - - this.generateLineSegment(theLeft2, mid, - child.left, theCenter); - } - } - } - }, - - retrieveStructure: function () { - var data = this.chart.structEngine; - var options = this.chart.options; - - var colLabels = data.getVisibleCategories(); - this.treeElements = data.getVisibleSeries(); - var values = data.getValues(); - - // if a fifth column is added, then - // bottom and height are provided in the dataset. - var bottomHeightSpecified = (colLabels.length > 4); - - var e; - - // trim al element labels (to allow for matching without spaces) - for(e in this.treeElements) { - this.treeElements[e] = $.trim(this.treeElements[e]); - } - - // get the bounds (minimal and maximum column and row indices) - // first a bounds object with two helper-functions is introduced - var bounds = []; - bounds.getElement = function(label) { - // create the element if it does not exist - if (bounds[label] == null){ - bounds[label] = {"min": +10000, "max": -10000}; - } - return bounds[label]; - }; - - bounds.addValue = function(label, value) { - var bnd = bounds.getElement(label); - if (value < bnd.min){ - bnd.min = value; - } - if (value > bnd.max){ - bnd.max = value; - } - return bnd; - }; - - var col, colnr, elem, row; - for(e in this.treeElements) { - elem = this.treeElements[e]; - col = elem[0]; - colnr = col.charCodeAt(0); - row = parseInt(elem.slice(1), 10); - bounds.addValue("__cols", colnr); - bounds.addValue(col,row); - } - - // determine parameters to find column-bounds - var bnds = bounds.getElement("__cols"); - var gridWidth = this.innerWidth/(bnds.max - bnds.min + 1); // integer - var connectorWidth = options.connectorSpace * gridWidth; - var cellWidth = gridWidth - connectorWidth; - var maxCellHeight = cellWidth/options.minAspectRatio; - var colBase = bnds.min; - delete bounds.__cols; - - // compute additional values for each column - for (e in bounds) { - bnds = bounds[e]; - - if (typeof bnds == "function"){ - continue; - } - var numRows = bnds.max - bnds.min + 1; - - bnds.gridHeight = this.innerHeight/numRows; - bnds.cellHeight = bnds.gridHeight*(1.0 - options.minVerticalSpace); - if (bnds.cellHeight > maxCellHeight){ - bnds.cellHeight = maxCellHeight; - } - bnds.relBottom = (bnds.gridHeight - bnds.cellHeight)/2; - bnds.numRows = numRows; - } - - // generate the elements - var whitespaceQuote = new RegExp ('[\\s\"\']+',"g"); - this.structMap = {}; - for(e in this.treeElements) { - var box = {}; - elem = this.treeElements[e]; - box.box_id = elem; - this.structMap[elem] = box; - - col = elem[0]; - colnr = col.charCodeAt(0); - row = parseInt(elem.slice(1), 10); - bnds = bounds.getElement(col); - - box.colIndex = colnr - colBase; - box.rowIndex = bnds.numRows - (row - bnds.min) - 1; - - box.left = this.leftOffs + box.colIndex * gridWidth; - box.width = cellWidth; - if (bottomHeightSpecified) { - box.bottom = values[4][e]; - box.height = values[5][e]; - } else { - box.bottom = this.botOffs + box.rowIndex * bnds.gridHeight + bnds.relBottom; - box.height = bnds.cellHeight; - } - - box.label = values[0][e]; - box.selector = values[1][e]; - box.aggregation = values[2][e]; - - var children = (values[3][e] || '').replace(whitespaceQuote, " "); - - box.children = (children === " " || children === "") ? - null : children.split(" "); - } - - this.generateConnectors((gridWidth - cellWidth)/2); - - // translate the map to an array (needed by protovis) - this.structArr = []; - for(e in this.structMap) { - elem = this.structMap[e]; - this.structArr.push(elem); - } - }, - - findDataValue: function(key, data) { - for(var i=0; i < data[0].length; i++) { - if (data[0][ i ] == key) { - return data[1][ i ]; - } - } - - this._log("Error: value with key : "+key+" not found."); - }, - - generateBoxPlots: function() { - var options = this.chart.options; - - for(var e in this.structArr) { - var elem = this.structArr[e]; - if (!elem.values.length) { - continue; - } - - elem.subplot = {}; - var sp = elem.subplot; - - // order the data elements from 5% bound to 95% bound - // and determine the horizontal scale - var dat = []; - var margin = 15; - var rlMargin = elem.width/6; - - // generate empty rule sets (existing sets are overwritten !) - sp.hRules = []; - sp.vRules = []; - sp.marks = []; - sp.labels = []; - - dat.push(this.findDataValue("_p5", elem.values)); - dat.push(this.findDataValue("_p25", elem.values)); - dat.push(this.findDataValue("_p50", elem.values)); - dat.push(this.findDataValue("_p75", elem.values)); - dat.push(this.findDataValue("_p95", elem.values)); - - var noBox = false; - - if (typeof(dat[2]) != "undefined") { - // switch order (assume computational artifact) - if (dat[4] < dat[0]) { - dat = dat.reverse(); - this._log(" dataset "+ elem.box_id + - " repaired (_p95 was smaller than _p5)"); - } - if (dat[4] > dat[0]) { - sp.hScale = pv.Scale.linear( dat[0], dat[4]); - } else { - noBox = true; - // generate a fake scale centered around dat[0] (== dat[4]) - sp.hScale = pv.Scale.linear( dat[0] - 1e-10, dat[0] + 1e-10); - } - sp.hScale.range(elem.left + rlMargin, elem.left + elem.width - rlMargin); - var avLabel = "" + dat[2]; // prepare the label - - var i; - - for(i=0; i< dat.length; i++) { - dat[i] = sp.hScale( dat[i]); - } - - sp.bot = elem.bottom + elem.height / 3; - sp.top = elem.bottom + 2 * elem.height / 3; - sp.mid = (sp.top + sp.bot) / 2; // 2/3 of height - sp.textBottom = elem.bottom + margin; - sp.textBottom = sp.bot - options.valueFontsize - 1; - - // and add the new set of rules for a box-plot. - var lwa = 3; // constant for "lineWidth Average" - if (noBox) { - sp.vRules.push({"left": dat[0], - "bottom": sp.bot, - "lWidth": lwa, - "height": sp.top - sp.bot}); - } else { - sp.hRules.push({"left": dat[0], - "width": dat[1] - dat[0], - "lWidth": 1, - "bottom": sp.mid}); - sp.hRules.push({"left": dat[1], - "width": dat[3] - dat[1], - "lWidth": 1, - "bottom": sp.bot}); - sp.hRules.push({"left": dat[1], - "width": dat[3] - dat[1], - "lWidth": 1, - "bottom": sp.top}); - sp.hRules.push({"left": dat[3], - "width": dat[4] - dat[3], - "lWidth": 1, - "bottom": sp.mid}); - for(i=0; i 0) && - (typeof window[selPar] != "undefined")) { - selPar = window[selPar]; - this.addDataPoint(selPar); - } - } - } , - - /** - * @override - */ - _createCore: function() { - - var myself = this; - - var options = this.chart.options; - options.smValueFontsize = Math.round(0.6 * options.valueFontsize); - options.smValueFont = "" + options.smValueFontsize + "px sans-serif"; - options.valueFont = "" + options.valueFontsize + "px sans-serif"; - - // used in the different closures - var topRuleOffs = options.topRuleOffset, - botRuleOffs = options.botRuleOffset, - leftRuleOffs = options.leftRuleOffset; - - // set a few parameters which will be used during data-retrieval - this.innerWidth = this.width - leftRuleOffs - options.rightRuleOffset; - this.innerHeight = this.height - topRuleOffs - botRuleOffs; - this.botOffs = botRuleOffs; - this.leftOffs = leftRuleOffs; - - // retrieve the data and transform it to the internal representation. - this.retrieveStructure(); - - this.retrieveData(); - - /***** - * Generate the scales x, y and color - *******/ - -/* -pv.Mark.prototype.property("testAdd"); - pv.Mark.prototype.testAdd = function(x) { -return pv.Label(x); - } -*/ - var topMargin = options.headerFontsize + 3; - - // draw the connectors first (rest has to drawn over the top) - var rules = this.rules; - var i; - - for (i = 0; i < rules.length; i++) { - /*jshint loopfunc:true */ - this.pvPanel.add(pv.Line) - .data(rules[ i ]) - .left(function(d) { return d.x;}) - .bottom(function(d) { return d.y;}) - .lineWidth(1) - .strokeStyle("black"); - } - - // draw the data containers with decorations - this.pvDataTree = this.pvPanel.add(pv.Bar) - .data(myself.structArr) - .left(function(d) { return d.left;}) - .bottom(function(d) { return d.bottom;}) - .height(function(d) { return d.height;}) - .width(function(d) { return d.width;}) - .fillStyle("green") -//; this.pvDataTree - .add(pv.Bar) -// .data(function(d) {return d; }) - .left(function(d) { return d.left + options.border;}) - .bottom(function(d) { return d.bottom + options.border;}) - .height(function(d) { return d.height - options.border - topMargin;}) - .width(function(d) { return d.width - 2 * options.border;}) - .fillStyle("white") - .add(pv.Label) - .text(function(d) { return d.label;}) - .textAlign("center") - .left(function (d) {return d.left + d.width/2;}) - .bottom(function(d) { - return d.bottom + d.height - options.headerFontsize - 5 + options.headerFontsize/5; -}) - .font("" + options.headerFontsize + "px sans-serif") - .textStyle("white") - .fillStyle("blue"); - - // add the box-plots - for(i=0; i - * The layout contains 5 target positions: top, bottom, left, right and center. - * These are mapped to a 3x3 grid. The corner cells always remain empty. - * In the center cell, panels are superimposed. - *

- *

- * Additionally, panels' paddings are shared: - * Left and right paddings are shared by the top, center and bottom panels. - * Top and bottom paddings are shared by the left, center and right panels. - *

- *

- * Child panel's can inform of existing overflowPaddings - - * resulting of things that are ok to overflow, - * as long as they don't leave the parent panel's space, - * and that the parent panel itself tries to reserve space for it or - * ensure it is in a free area. - *

- *

- * The empty corner cells of the grid layout can absorb some of the overflow - * content from non-fill child panels. - * If, for example, a child panel is placed at the 'left' cell and it - * overflows in 'top', that overflow can be partly absorbed by - * the top-left corner cell, as long as there's a panel in the top cell that - * imposes that much height. - *

- *

- * If the corner space is not enough to absorb the overflow paddings - * - *

- * - * @override - */ - _calcLayout: function(layoutInfo){ - var me = this; - - if(!me._children) { - return; - } - - var useLog = pvc.debug >= 5; - - // Objects we can mutate - var margins = new pvc.Sides(0); - var paddings = new pvc.Sides(0); - var remSize = def.copyOwn(layoutInfo.clientSize); - var aolMap = pvc.BasePanel.orthogonalLength; - var aoMap = pvc.BasePanel.relativeAnchor; - var alMap = pvc.BasePanel.parallelLength; - - var childKeyArgs = { - force: true, - referenceSize: layoutInfo.clientSize - }; - - var fillChildren = []; - var sideChildren = []; - - // loop detection - var paddingHistory = {}; - - var LoopDetected = 1; - var NormalPaddingsChanged = 2; - var OverflowPaddingsChanged = 4; - - var emptyNewPaddings = new pvc.Sides(); // used below in place of null requestPaddings - var isDisasterRecovery = false; - - if(useLog){ me._group("CCC GRID LAYOUT clientSize = " + pvc.stringify(remSize)); } - try{ - // PHASE 0 - Initialization - // - // Splits children in two groups: FILL and SIDE, according to its anchor. - // Children explicitly not requiring layout are excluded (!child.anchor). - // - // For FILL children, finds the maximum of the resolved paddings. - // These paddings will be the minimum that will result from this layout. - /*global console:true*/ - this._children.forEach(initChild); - - // PHASE 1 - "MARGINS" are imposed by SIDE children - // - // Lays out non-fill children receiving each, the remaining space as clientSize. - // - // Each adds its orthogonal length to the margin side where it is anchored. - // The normal length is only correctly known after all non-fill - // children have been laid out once. - // - // As such the child is only positioned on the anchor coordinate. - // The orthogonal anchor coordinate is only set on the second phase. - // - // SIDE children may change paddings as well. - if(useLog){ me._group("Phase 1 - Determine MARGINS and FILL SIZE from SIDE panels"); } - try{ - sideChildren.forEach(layoutChild1Side); - } finally { - // -> remSize now contains the size of the CENTER cell and is not changed any more - - if(useLog){ - me._groupEnd(); - me._log("Final FILL margins = " + pvc.stringify(margins)); - me._log("Final FILL border size = " + pvc.stringify(remSize)); - } - } - - // PHASE 2 - Relayout each SIDE child with its final orthogonal length - // PHASE 3 - Layout FILL children - // - // Repeat 2 and 3 while paddings changed - if(useLog){ me._group("Phase 2 - Determine COMMON PADDINGS"); } - try{ - doMaxTimes(9, layoutCycle); - } finally { - if(useLog){ - me._groupEnd(); - me._log("Final FILL clientSize = " + pvc.stringify({width: (remSize.width - paddings.width), height: (remSize.height - paddings.height)})); - me._log("Final COMMON paddings = " + pvc.stringify(paddings)); - } - } - - layoutInfo.gridMargins = new pvc.Sides(margins ); - layoutInfo.gridPaddings = new pvc.Sides(paddings); - layoutInfo.gridSize = new pvc.Size(remSize ); - - // All available client space is consumed. - // As such, there's no need to return anything. - // return; - } finally { - if(useLog){ me._groupEnd(); } - } - - // -------- - - function layoutCycle(remTimes, iteration){ - if(useLog){ me._group("LayoutCycle " + (isDisasterRecovery ? "- Disaster MODE" : ("#" + (iteration + 1)))); } - try{ - var index, count; - var canChange = layoutInfo.canChange !== false && !isDisasterRecovery && (remTimes > 0); - var paddingsChanged; - var ownPaddingsChanged = false; - var breakAndRepeat; - - index = 0; - count = sideChildren.length; - while(index < count){ - if(useLog){ me._group("SIDE Child #" + (index + 1)); } - try{ - paddingsChanged = layoutChild2Side(sideChildren[index], canChange); - if(!isDisasterRecovery && paddingsChanged){ - breakAndRepeat = false; - if((paddingsChanged & OverflowPaddingsChanged) !== 0){ - // Don't stop right away cause there might be - // other overflow paddings requests, - // of other side childs. - // Translate children overflow paddings in - // own paddings. - if(useLog){ me._log("SIDE Child #" + (index + 1) + " changed overflow paddings"); } - if(!ownPaddingsChanged){ - ownPaddingsChanged = true; - // If others change we don't do nothing. - // The previous assignment remains. - // It's layoutInfo.paddings that is changed, internally. - layoutInfo.requestPaddings = layoutInfo.paddings; - } - } - - if((paddingsChanged & NormalPaddingsChanged) !== 0){ - if(remTimes > 0){ - if(useLog){ me._log("SIDE Child #" + (index + 1) + " changed normal paddings"); } - breakAndRepeat = true; - } else if(pvc.debug >= 2){ - me._warn("SIDE Child #" + (index + 1) + " changed paddings but no more iterations possible."); - } - } - - if((paddingsChanged & LoopDetected) !== 0){ - // Oh no... - isDisasterRecovery = true; - - layoutCycle(0); - - return false; // stop; - } - - if(breakAndRepeat) { - return true; - } - } - } finally { - if(useLog){ me._groupEnd(); } - } - index++; - } - - if(ownPaddingsChanged){ - if(useLog){ me._log("Restarting due to overflowPaddings change"); } - return false; // stop; - } - - index = 0; - count = fillChildren.length; - while(index < count){ - if(useLog){ me._group("FILL Child #" + (index + 1)); } - try{ - paddingsChanged = layoutChildFill(fillChildren[index], canChange); - if(!isDisasterRecovery && paddingsChanged){ - breakAndRepeat = false; - - if((paddingsChanged & NormalPaddingsChanged) !== 0){ - if(remTimes > 0){ - if(pvc.debug >= 5){ - me._log("FILL Child #" + (index + 1) + " increased paddings"); - } - breakAndRepeat = true; // repeat - } else if(pvc.debug >= 2){ - me._warn("FILL Child #" + (index + 1) + " increased paddings but no more iterations possible."); - } - } - - if((paddingsChanged & LoopDetected) !== 0){ - // Oh no... - isDisasterRecovery = true; - layoutCycle(0); - return false; // stop; - } - - if(breakAndRepeat) { - return true; - } - } - } finally { - if(useLog){ me._groupEnd(); } - } - - index++; - } - - return false; // stop - } finally { - if(useLog){ me._groupEnd(); } - } - } - - function doMaxTimes(maxTimes, fun){ - var index = 0; - while(maxTimes--){ - // remTimes = maxTimes - if(fun(maxTimes, index) === false){ - return true; - } - index++; - } - - return false; - } - - function initChild(child) { - var a = child.anchor; - if(a){ - if(a === 'fill') { - fillChildren.push(child); - - var childPaddings = child.paddings.resolve(childKeyArgs.referenceSize); - - // After the op. it's not a pvc.Side anymore, just an object with same named properties. - paddings = pvc.Sides.resolvedMax(paddings, childPaddings); - } else { - /*jshint expr:true */ - def.hasOwn(aoMap, a) || def.fail.operationInvalid("Unknown anchor value '{0}'", [a]); - - sideChildren.push(child); - } - } - } - - function layoutChild1Side(child, index) { - if(useLog){ me._group("SIDE Child #" + (index + 1)); } - try{ - var paddingsChanged = 0; - - var a = child.anchor; - - childKeyArgs.paddings = filterAnchorPaddings(a, paddings); - - child.layout(new pvc.Size(remSize), childKeyArgs); - - if(child.isVisible){ - - paddingsChanged |= checkAnchorPaddingsChanged(a, paddings, child); - - // Only set the *anchor* position - // The other orthogonal position is dependent on the size of the other non-fill children - positionChildNormal(a, child); - - updateSide(a, child); - } - - return paddingsChanged; - } finally { - if(useLog){ me._groupEnd(); } - } - } - - function layoutChildFill(child, canChange) { - var paddingsChanged = 0; - - var a = child.anchor; // 'fill' - - childKeyArgs.paddings = filterAnchorPaddings(a, paddings); - childKeyArgs.canChange = canChange; - - child.layout(new pvc.Size(remSize), childKeyArgs); - - if(child.isVisible){ - paddingsChanged |= checkAnchorPaddingsChanged(a, paddings, child, canChange); - - positionChildNormal(a, child); - positionChildOrtho (child, a); - } - - return paddingsChanged; - } - - function layoutChild2Side(child, canChange) { - var paddingsChanged = 0; - if(child.isVisible){ - var a = child.anchor; - var al = alMap[a]; - var aol = aolMap[a]; - var length = remSize[al]; - var olength = child[aol]; - - var childSize2 = new pvc.Size(def.set({}, al, length, aol, olength)); - - childKeyArgs.paddings = filterAnchorPaddings(a, paddings); - childKeyArgs.canChange = canChange; - - child.layout(childSize2, childKeyArgs); - - if(child.isVisible){ - paddingsChanged = checkAnchorPaddingsChanged(a, paddings, child, canChange) | // <-- NOTE BITwise OR - checkOverflowPaddingsChanged(a, layoutInfo.paddings, child, canChange); - - if(!paddingsChanged){ - positionChildOrtho(child, child.align); - } - } - } - - return paddingsChanged; - } - - function positionChildNormal(side, child) { - var sidePos; - if(side === 'fill'){ - side = 'left'; - sidePos = margins.left + remSize.width / 2 - (child.width / 2); - } else { - sidePos = margins[side]; - } - - child.setPosition(def.set({}, side, sidePos)); - } - - // Decreases available size and increases margins - function updateSide(side, child) { - var sideol = aolMap[side], - olen = child[sideol]; - - margins[side] += olen; - remSize[sideol] -= olen; - } - - function positionChildOrtho(child, align) { - var sideo; - if(align === 'fill'){ - align = 'middle'; - } - - var sideOPos; - switch(align){ - case 'top': - case 'bottom': - case 'left': - case 'right': - sideo = align; - sideOPos = margins[sideo]; - break; - - case 'middle': - sideo = 'bottom'; - sideOPos = margins.bottom + (remSize.height / 2) - (child.height / 2); - break; - - case 'center': - sideo = 'left'; - sideOPos = margins.left + remSize.width / 2 - (child.width / 2); - break; - } - - child.setPosition(def.set({}, sideo, sideOPos)); - } - - function filterAnchorPaddings(a, paddings){ - var filtered = new pvc.Sides(); - - getAnchorPaddingsNames(a).forEach(function(side){ - filtered.set(side, paddings[side]); - }); - - return filtered; - } - - function checkAnchorPaddingsChanged(a, paddings, child, canChange){ - var newPaddings = child._layoutInfo.requestPaddings; - - var changed = 0; - - // Additional paddings are requested? - if(newPaddings){ - if(useLog && pvc.debug >= 10){ - me._log("=> clientSize=" + pvc.stringify(child._layoutInfo.clientSize)); - me._log("<= requestPaddings=" + pvc.stringify(newPaddings)); - } - - // Compare requested paddings with existing paddings - getAnchorPaddingsNames(a).forEach(function(side){ - var value = paddings[side] || 0; - var newValue = Math.floor(10000 * (newPaddings[side] || 0)) / 10000; - var increase = newValue - value; - var minChange = Math.max(1, Math.abs(0.01 * value)); - - // STABILITY requirement - if(increase !== 0 && Math.abs(increase) >= minChange){ - if(!canChange){ - if(pvc.debug >= 2){ - me._warn("CANNOT change but child wanted to: " + side + "=" + newValue); - } - } else { - changed |= NormalPaddingsChanged; - paddings[side] = newValue; - - if(useLog){ - me._log("Changed padding " + side + " <- " + newValue); - } - } - } - }); - - if(changed){ - var paddingKey = pvc.Sides - .names - .map(function(side){ return (paddings[side] || 0).toFixed(0); }) - .join('|'); - - if(def.hasOwn(paddingHistory, paddingKey)){ - // LOOP detected - if(pvc.debug >= 2){ - me._warn("LOOP detected!!!!"); - } - changed |= LoopDetected; - } else { - paddingHistory[paddingKey] = true; - } - - paddings.width = paddings.left + paddings.right ; - paddings.height = paddings.top + paddings.bottom; - } - } - - return changed; - } - - function checkOverflowPaddingsChanged(a, ownPaddings, child, canChange){ - var overflowPaddings = child._layoutInfo.overflowPaddings || emptyNewPaddings; - - var changed = 0; - - if(useLog && pvc.debug >= 10){ - me._log("<= overflowPaddings=" + pvc.stringify(overflowPaddings)); - } - - getAnchorPaddingsNames(a).forEach(function(side){ - if(overflowPaddings.hasOwnProperty(side)){ - var value = ownPaddings[side] || 0; - var newValue = Math.floor(10000 * (overflowPaddings[side] || 0)) / 10000; - newValue -= margins[side]; // corners absorb some of it - - var increase = newValue - value; - var minChange = Math.max(1, Math.abs(0.05 * value)); - - // STABILITY & SPEED requirement - if(increase >= minChange){ - if(!canChange){ - if(pvc.debug >= 2){ - me._warn("CANNOT change overflow padding but child wanted to: " + side + "=" + newValue); - } - } else { - changed |= OverflowPaddingsChanged; - ownPaddings[side] = newValue; - - if(useLog){ - me._log("changed overflow padding " + side + " <- " + newValue); - } - } - } - } - }); - - if(changed){ - ownPaddings.width = ownPaddings.left + ownPaddings.right ; - ownPaddings.height = ownPaddings.top + ownPaddings.bottom; - } - - return changed; - } - - function getAnchorPaddingsNames(a){ - switch(a){ - case 'left': - case 'right': return pvc.Sides.vnames; - case 'top': - case 'bottom': return pvc.Sides.hnames; - case 'fill': return pvc.Sides.names; - } - } - } -}); diff --git a/pacotes/ccc2/pvc/pvcHeatGridChart.js b/pacotes/ccc2/pvc/pvcHeatGridChart.js deleted file mode 100755 index 0ec7049..0000000 --- a/pacotes/ccc2/pvc/pvcHeatGridChart.js +++ /dev/null @@ -1,159 +0,0 @@ - -/** - * HeatGridChart is the main class for generating... heatGrid charts. - * A heatGrid visualizes a matrix of values by a grid (matrix) of * - * bars, where the color of the bar represents the actual value. - * By default the colors are a range of green values, where - * light green represents low values and dark green high values. - * A heatGrid contains: - * - two categorical axis (both on x and y-axis) - * - no legend as series become rows on the perpendicular axis - * Please contact CvK if there are issues with HeatGrid at cde@vinzi.nl. - */ -def -.type('pvc.HeatGridChart', pvc.CategoricalAbstract) -.add({ - _allowColorPerCategory: true, - - // Create color axis, even if the role is unbound - // cause we need to check the axis options any way - _axisCreateIfUnbound: { - 'color': true - }, - - _processOptionsCore: function(options){ - - this.base(options); - - def.set(options, - 'orthoAxisOrdinal', true, - 'legend', false, - - // Has no meaning in the current implementation - 'panelSizeRatio', 1); - - // TODO: get a translator for this!! - - var colorDimName = 'value', - sizeDimName = 'value2'; - - if(this.compatVersion() <= 1){ - switch(this.options.colorValIdx){ - case 0: colorDimName = 'value'; break; - case 1: colorDimName = 'value2'; break; - default: colorDimName = 'value'; - } - - switch(this.options.sizeValIdx){ - case 0: sizeDimName = 'value' ; break; - case 1: sizeDimName = 'value2'; break; - default: sizeDimName = 'value' ; - } - } - - this._colorDimName = colorDimName; - this._sizeDimName = sizeDimName ; - }, - - _getCategoryRoleSpec: function(){ - var catRoleSpec = this.base(); - - // Force dimension to be discrete! - catRoleSpec.requireIsDiscrete = true; - - return catRoleSpec; - }, - - _getColorRoleSpec: function(){ - return { - isMeasure: true, - requireSingleDimension: true, - requireIsDiscrete: false, - valueType: Number, - defaultDimension: this._colorDimName - }; - }, - - /** - * Initializes each chart's specific roles. - * @override - */ - _initVisualRoles: function(){ - - this.base(); - - this._addVisualRole('size', { - isMeasure: true, - requireSingleDimension: true, - requireIsDiscrete: false, - valueType: Number, - defaultDimension: this._sizeDimName - }); - }, - - _initPlotsCore: function(/*hasMultiRole*/){ - new pvc.visual.HeatGridPlot(this); - }, - - _collectPlotAxesDataCells: function(plot, dataCellsByAxisTypeThenIndex){ - - this.base(plot, dataCellsByAxisTypeThenIndex); - - /* Configure Base Axis Data Cell */ - if(plot.type === 'heatGrid' && plot.option('UseShapes')){ - - var sizeRole = this.visualRoles(plot.option('SizeRole')); - if(sizeRole.isBound()){ - - var sizeDataCellsByAxisIndex = - def - .array - .lazy(dataCellsByAxisTypeThenIndex, 'size'); - - def - .array - .lazy(sizeDataCellsByAxisIndex, plot.option('SizeAxis') - 1) - .push({ - plot: plot, - role: sizeRole, - dataPartValue: plot.option('DataPart') - }); - } - } - }, - - _setAxesScales: function(hasMultiRole){ - - this.base(hasMultiRole); - - if(!hasMultiRole || this.parent){ - - var sizeAxis = this.axes.size; - if(sizeAxis && sizeAxis.isBound()){ - this._createAxisScale(sizeAxis); - } - } - }, - - /* @override */ - _createPlotPanels: function(parentPanel, baseOptions){ - var heatGridPlot = this.plots.heatGrid; - - this.heatGridChartPanel = - new pvc.HeatGridPanel( - this, - parentPanel, - heatGridPlot, - Object.create(baseOptions)); - }, - - defaults: { - colorValIdx: 0, - sizeValIdx: 1, - measuresIndexes: [2], // TODO: ??? - axisOffset: 0, - plotFrameVisible: false, - colorNormByCategory: true, - numSD: 2 // width (only for normal distribution) - } -}); diff --git a/pacotes/ccc2/pvc/pvcHeatGridPanel.js b/pacotes/ccc2/pvc/pvcHeatGridPanel.js deleted file mode 100755 index 102d87c..0000000 --- a/pacotes/ccc2/pvc/pvcHeatGridPanel.js +++ /dev/null @@ -1,519 +0,0 @@ - -/* - * HeatGrid chart panel. Generates a heatGrid chart. Specific options are: - * orientation - horizontal or vertical. Default: vertical - * valuesVisible - Show or hide heatGrid value. Default: false - * maxHeatGridSize - Maximum size of a heatGrid in pixels. Default: 2000 - * - * Has the following protovis extension points: - * - * chart_ - for the main chart Panel - * heatGrid_ - for the actual heatGrid - * heatGridPanel_ - for the panel where the heatGrids sit - * heatGridLabel_ - for the main heatGrid label - */ -def -.type('pvc.HeatGridPanel', pvc.CategoricalAbstractPanel) -.init(function(chart, parent, plot, options) { - - this.base(chart, parent, plot, options); - - this.axes.size = chart._getAxis('size', plot.option('SizeAxis') - 1); // may be undefined - - var roles = this.visualRoles; - - var sizeRoleName = plot.option('SizeRole'); // assumed to be always defined - roles.size = chart.visualRoles(sizeRoleName); - - var valueDimName; - if(roles.color.isBound()){ // assumed to always exist on this chart type - valueDimName = roles.color.firstDimensionName(); - } else if(roles.size.isBound()){ - valueDimName = roles.size.firstDimensionName(); - } - this._valueDimName = valueDimName; - - this.useShapes = plot.option('UseShapes'); - this.shape = plot.option('Shape'); - this.nullShape = plot.option('NullShape'); -}) -.add({ - - pvHeatGrid: null, - pvHeatGridLabel: null, - - defaultBorder: 1, - nullBorder: 2, - selectedBorder: 2, - - /** - * @override - */ - _createCore: function(){ - - this.base(); - - // TODO: this options treatment is highly "non-standard". Refactor to chart + panel-constructor - - var chart = this.chart; - var a_bottom = this.isOrientationVertical() ? "bottom" : "left"; - - /* Use existing scales */ - var xScale = this.axes.x.scale; - var yScale = this.axes.y.scale; - - /* Determine cell dimensions. */ - var w = (xScale.max - xScale.min) / xScale.domain().length; - var h = (yScale.max - yScale.min) / yScale.domain().length; - - if (a_bottom !== "bottom") { - var tmp = w; - w = h; - h = tmp; - } - - this._cellWidth = w; - this._cellHeight = h; - - /* Column and Row datas */ - var keyArgs = {visible: true}, - // One multi-dimension single-level data grouping - rowRootData = chart.data.flattenBy(chart._serRole, keyArgs), - - // One multi-dimensional, two-levels data grouping - data = this.visibleData(), - - rootScene = this._buildScene(data, rowRootData), - hasColor = rootScene.hasColorRole, - hasSize = rootScene.hasSizeRole - ; - - /* COLOR */ - - var getFillColor; - var colorAxis = this.axes.color; - var colorNull = colorAxis.option('Missing'); - if(hasColor){ - var fillColorScaleByColKey = colorAxis.scalesByCateg; - if(fillColorScaleByColKey){ - getFillColor = function(leafScene){ - var colorValue = leafScene.vars.color.value; - if(colorValue == null) { - return colorNull; - } - - var colAbsKey = leafScene.group.parent.absKey; - return fillColorScaleByColKey[colAbsKey](colorValue); - }; - } else { - var colorScale = colorAxis.scale; - getFillColor = function(leafScene){ - return colorScale(leafScene.vars.color.value); - }; - } - } else { - getFillColor = def.fun.constant(colorNull); - } - - /* PV Panels */ - var a_left = pvc.BasePanel.relativeAnchor[a_bottom]; - var a_width = pvc.BasePanel.parallelLength[a_bottom]; - var a_height = pvc.BasePanel.orthogonalLength[a_bottom]; - - var pvRowPanel = new pvc.visual.Panel(this, this.pvPanel) - .pvMark - .data(rootScene.childNodes) - [a_bottom](function(){ return this.index * h; }) - [a_height](h) - ; - - var wrapper; - if(this.compatVersion() <= 1){ - var colorValuesBySerAndCat = - def - .query(rootScene.childNodes) - .object({ - name: function(serScene){ return '' + serScene.vars.series.value; }, - value: function(serScene){ - return def - .query(serScene.childNodes) - .object({ - name: function(leafScene){ return '' + leafScene.vars.category.value; }, - value: function(leafScene){ - var colorVar = leafScene.vars.color; - return colorVar ? ('' + colorVar.value) : null; - } - }); - } - }); - - wrapper = function(v1f){ - return function(leafScene){ - var colorValuesByCat = colorValuesBySerAndCat[leafScene.vars.series.value]; - var cat = leafScene.vars.category.rawValue; - - var wrapperParent = Object.create(this.parent); - var wrapper = Object.create(this); - wrapper.parent = wrapperParent; - - // Previously, first panel was by cats and - // the second (child) panel was by series - var catIndex = leafScene.childIndex(); - var serIndex = leafScene.parent.childIndex(); - - wrapperParent.index = catIndex; - wrapper.index = serIndex; - - return v1f.call(wrapper, colorValuesByCat, cat); - }; - }; - } - - /* Cell panel */ - var extensionIds = ['panel']; - if(this.compatVersion() <= 1){ - extensionIds.push(''); // let access as "heatGrid_" - } - - keyArgs = { // reuse var - extensionId: extensionIds, - wrapper: wrapper - }; - - if(!this.useShapes){ - // When no shapes are used, - // clicks, double-clicks and tooltips are all handled by - // the cell panel - keyArgs.noSelect = - keyArgs.noHover = - keyArgs.noClick = - keyArgs.noDoubleClick = - keyArgs.freeColor = false; - - keyArgs.noTooltip = !!wrapper; // V1 had no tooltips - } - - var pvHeatGrid = this.pvHeatGrid = new pvc.visual.Panel(this, pvRowPanel, keyArgs) - .lock('data', function(serScene){ return serScene.childNodes; }) - .pvMark - - .localProperty('colorValue') - .lock('colorValue', function(leafScene){ return leafScene.vars.color.value; }) - - .localProperty('sizeValue') - .lock('sizeValue', function(leafScene){ return leafScene.vars.size .value; }) - - .lock(a_left, function(){ return this.index * w; }) - .lock(a_width, w) - - .antialias(false) - //.lineWidth(0) - ; - // THIS caused HUGE memory consumption and speed reduction (at least in use Shapes mode) - //.overflow('hidden'); //overflow important if valuesVisible=true - - - if(this.useShapes){ - this.shapes = this.createHeatMap(w, h, getFillColor, wrapper, hasColor, hasSize); - } else { - this.shapes = pvHeatGrid - .sign - .override('defaultColor', function(type){ - if(type === 'stroke'){ - return null; - } - - return getFillColor.call(this.pvMark, this.scene); - }) - .override('interactiveColor', function(color, type){ - var scene = this.scene; - if(scene.isActive) { - return color.alpha(0.6); - } - - if(scene.anySelected() && !scene.isSelected()) { - return this.dimColor(color, type); - } - - return this.base(color, type); - }) - .override('dimColor', function(color/*, type*/){ - return pvc.toGrayScale(color, 0.6); - }) - .pvMark - .lineWidth(1.5) - ; - } - - // TODO: valueMask?? - if(this.valuesVisible && this._valueDimName){ - var valueDimName = this._valueDimName; - this.pvHeatGridLabel = new pvc.visual.Label( - this, - this.pvHeatGrid.anchor("center"), - { - extensionId: 'label', - wrapper: wrapper - }) - .pvMark - .font(this.valuesFont) // default - .text(function(leafScene){ - return leafScene.atoms[valueDimName].label; - }) - ; - } - }, - - _calcDotAreaRange: function(w, h){ - - var maxRadius = Math.min(w, h) / 2; - - if(this.shape === 'diamond'){ - // Protovis draws diamonds inscribed on - // a square with half-side radius*Math.SQRT2 - // (so that diamonds just look like a rotated square) - // For the height of the dimanod not to exceed the cell size - // we compensate that factor here. - maxRadius /= Math.SQRT2; - } - - // Small margin - maxRadius -= 2; - - var maxArea = maxRadius * maxRadius, // apparently treats as square area even if circle, triangle is different - minArea = 12, - areaSpan = maxArea - minArea; - - if(areaSpan <= 1){ - // Very little space - // Rescue Mode - show *something* - maxArea = Math.max(maxArea, 2); - minArea = 1; - areaSpan = maxArea - minArea; - - if(pvc.debug >= 2){ - this._log("Using rescue mode dot area calculation due to insufficient space."); - } - } - - return { - min: minArea, - max: maxArea, - span: areaSpan - }; - }, - - createHeatMap: function(w, h, getFillColor, wrapper, hasColor, hasSize){ - var me = this, - chart = me.chart, - nullShapeType = me.nullShape, - shapeType = me.shape; - - /* SIZE */ - var areaRange = me._calcDotAreaRange(w, h); - var maxArea = areaRange.max; - - var sizeScale; - if(hasSize){ - sizeScale = me.axes.size - .setScaleRange(areaRange) - .scale; - } - - /* BORDER WIDTH & COLOR */ - var notNullSelectedBorder = (me.selectedBorder == null || (+me.selectedBorder) === 0) ? - me.defaultBorder : - me.selectedBorder; - - var nullSelectedBorder = (me.selectedBorder == null || (+me.selectedBorder) === 0) ? - me.nullBorder : - me.selectedBorder; - - var nullDeselectedBorder = me.defaultBorder > 0 ? me.defaultBorder : me.nullBorder; - - /* SHAPE TYPE & SIZE */ - var getShapeSize, getShapeType; - if(!hasSize){ - getShapeType = def.fun.constant(shapeType); - getShapeSize = function(){ - /* When neither color nor size dimensions */ - return (hasColor && !nullShapeType && this.parent.colorValue() == null) ? 0 : maxArea; - }; - } else { - getShapeType = function(){ - return this.parent.sizeValue() != null ? shapeType : nullShapeType; - }; - getShapeSize = function(){ - var sizeValue = this.parent.sizeValue(); - return (sizeValue == null && !nullShapeType) ? 0 : sizeScale(sizeValue); - }; - } - - // Dot - var keyArgs = { - extensionId: 'dot', - freePosition: true, - activeSeriesAware: false, - noHover: false, - wrapper: wrapper - }; - - var options = chart.options; - if(wrapper && chart._tooltipEnabled){ - var customTooltip = options.customTooltip; - if(!customTooltip){ - customTooltip = function(s,c,d){ - if(d != null && d[0] !== undefined){ - return d.join(', '); - } - return d; - }; - } - - keyArgs.tooltipArgs = { - buildTooltip: - options.isMultiValued ? - function(context){ - var group = context.scene.group; - var s = pvc.data.Complex.values(group, chart._serRole.grouping.dimensionNames()); - var c = pvc.data.Complex.values(group, chart._catRole.grouping.dimensionNames()); - - var d = []; - if(hasSize){ - d[options.sizeValIdx || 0] = context.scene.vars.size.value; - } - if(hasColor){ - d[options.colorValIdx || 0] = context.scene.vars.color.value; - } - - return customTooltip.call(options, s, c, d); - } : - function(context){ - var s = context.scene.vars.series.rawValue; - var c = context.scene.vars.category.rawValue; - var valueVar = context.scene.vars[hasColor ? 'color' : 'size']; - var d = valueVar ? valueVar.value : null; - return customTooltip.call(options, s, c, d); - } - }; - } - - return new pvc.visual.Dot(me, me.pvHeatGrid, keyArgs) - .override('defaultSize', function(){ - return getShapeSize.call(this.pvMark, this.scene); - }) - .override('interactiveSize', function(size){ - if(this.scene.isActive){ - return Math.max(size, 5) * 1.5; - } - - return size; - }) - .override('baseColor', function(/*type*/){ - return getFillColor.call(this.pvMark.parent, this.scene); - }) - .override('normalColor', function(color, type){ - if(type === 'stroke'){ - return color.darker(); - } - - return this.base(color, type); - }) - .override('interactiveColor', function(color, type){ - var scene = this.scene; - - if(type === 'stroke'){ - if(scene.anySelected() && !scene.isSelected()){ - return color; - } - - return color.darker(); - } - - if(scene.isActive){ - return color.alpha(0.6); - } - - return this.base(color, type); - }) - .override('dimColor', function(color/*, type*/){ - return pvc.toGrayScale(color, 0.6); - }) - .pvMark - - .shape(getShapeType) - - .lock('shapeAngle') // rotation of shapes can cause them to not fit the calculated cell. Would have to improve the radius calculation code. - - .lineWidth(function(leafScene){ - if(!hasSize || !me._isNullShapeLineOnly() || this.parent.sizeValue() != null){ - return leafScene.isSelected() ? notNullSelectedBorder : me.defaultBorder; - } - - // is null - return leafScene.isSelected() ? nullSelectedBorder : nullDeselectedBorder; - }) - ; - }, - - _isNullShapeLineOnly: function(){ - return this.nullShape == 'cross'; - }, - - /** - * Returns an array of marks whose instances are associated to a datum, or null. - * @override - */ - _getSelectableMarks: function(){ - return [this.shapes]; - }, - - /** - * Renders the heat grid panel. - * @override - */ - renderInteractive: function(){ - this.pvPanel.render(); - }, - - _buildScene: function(data, seriesRootData){ - var me = this; - var rootScene = new pvc.visual.Scene(null, {panel: me, group: data}); - var categDatas = data._children; - - var roles = me.visualRoles; - var colorVarHelper = new pvc.visual.RoleVarHelper(rootScene, roles.color); - var sizeVarHelper = new pvc.visual.RoleVarHelper(rootScene, roles.size); - - rootScene.hasColorRole = colorVarHelper.isBound(); - rootScene.hasSizeRole = sizeVarHelper .isBound(); - - seriesRootData - .children() - .each(createSeriesScene); - - return rootScene; - - function createSeriesScene(serData1){ - /* Create series scene */ - var serScene = new pvc.visual.Scene(rootScene, {group: serData1}); - - serScene.vars.series = pvc.visual.ValueLabelVar.fromComplex(serData1); - - categDatas.forEach(function(catData1){ - createSeriesCategoryScene.call(me, serScene, catData1, serData1); - }); - } - - function createSeriesCategoryScene(serScene, catData1, serData1){ - var group = data._childrenByKey[catData1.key]._childrenByKey[serData1.key]; - - var serCatScene = new pvc.visual.Scene(serScene, {group: group}); - - serCatScene.vars.category = pvc.visual.ValueLabelVar.fromComplex(catData1); - - colorVarHelper.onNewScene(serCatScene, /* isLeaf */true); - sizeVarHelper .onNewScene(serCatScene, /* isLeaf */true); - } - } -}); diff --git a/pacotes/ccc2/pvc/pvcLegendPanel.js b/pacotes/ccc2/pvc/pvcLegendPanel.js deleted file mode 100755 index 40722d8..0000000 --- a/pacotes/ccc2/pvc/pvcLegendPanel.js +++ /dev/null @@ -1,229 +0,0 @@ - -/* - * Legend panel. Generates the legend. Specific options are: - * legendPosition - top / bottom / left / right. Default: bottom - * legendSize - The size of the legend in pixels. Default: 25 - * - * Has the following protovis extension points: - * - * legend_ - for the legend Panel - * legendRule_ - for the legend line (when applicable) - * legendDot_ - for the legend marker (when applicable) - * legendLabel_ - for the legend label - * - */ -def -.type('pvc.LegendPanel', pvc.BasePanel) -.add({ - pvRule: null, - pvDot: null, - pvLabel: null, - - anchor: 'bottom', - - pvLegendPanel: null, - - textMargin: 6, // The space *between* the marker and the text, in pixels. - itemPadding: 2.5, // Half the space *between* legend items, in pixels. - markerSize: 15, // *diameter* of marker *zone* (the marker itself may be a little smaller) - font: '10px sans-serif', - - /** - * @override - */ - _calcLayout: function(layoutInfo){ - return this._getBulletRootScene().layout(layoutInfo); - }, - - /** - * @override - */ - _createCore: function(layoutInfo) { - var clientSize = layoutInfo.clientSize, - rootScene = this._getBulletRootScene(), - itemPadding = rootScene.vars.itemPadding, - contentSize = rootScene.vars.size; - - // Names are for horizontal layout (anchor = top or bottom) - var isHorizontal = this.isAnchorTopOrBottom(); - var a_top = isHorizontal ? 'top' : 'left'; - var a_bottom = this.anchorOpposite(a_top); // top or bottom - var a_width = this.anchorLength(a_top); // width or height - var a_height = this.anchorOrthoLength(a_top); // height or width - var a_center = isHorizontal ? 'center' : 'middle'; - var a_left = isHorizontal ? 'left' : 'top'; - var a_right = this.anchorOpposite(a_left); // left or right - - // When V1 compat or size is fixed to less/more than content needs, - // it is still needed to align content inside - - // We align all rows left (or top), using the length of the widest row. - // So "center" is a kind of centered-left align? - - var leftOffset = 0; - switch(this.align){ - case a_right: - leftOffset = clientSize[a_width] - contentSize.width; - break; - - case a_center: - leftOffset = (clientSize[a_width] - contentSize.width) / 2; - break; - } - - this.pvPanel.overflow("hidden"); - - // ROW - A panel instance per row - var pvLegendRowPanel = this.pvPanel.add(pv.Panel) - .data(rootScene.vars.rows) // rows are "lists" of bullet item scenes - [a_left ](leftOffset) - [a_top ](function(){ - var prevRow = this.sibling(); - return prevRow ? (prevRow[a_top] + prevRow[a_height] + itemPadding[a_height]) : 0; - }) - [a_width ](function(row){ return row.size.width; }) - [a_height](function(row){ return row.size.height; }) - ; - - var wrapper; - if(this.compatVersion() <= 1){ - wrapper = function(v1f){ - return function(itemScene){ - return v1f.call(this, itemScene.vars.value.rawValue); - }; - }; - } - - // ROW > ITEM - A pvLegendPanel instance per bullet item in a row - this.pvLegendPanel = new pvc.visual.Panel(this, pvLegendRowPanel, { - extensionId: 'panel', - wrapper: wrapper, - noSelect: false, - noClickSelect: true // just rubber-band (the click is for other behaviors) - }) - .lockMark('data', function(row){ return row.items; }) // each row has a list of bullet item scenes - .lock(a_right, null) - .lock(a_bottom, null) - .lockMark(a_left, function(clientScene){ - var itemPadding = clientScene.vars.itemPadding; - var prevItem = this.sibling(); - return prevItem ? - (prevItem[a_left] + prevItem[a_width] + itemPadding[a_width]) : - 0; - }) - .lockMark('height', function(itemScene){ return itemScene.vars.clientSize.height; }) - .lockMark(a_top, - isHorizontal ? - // Center items in row's height, that may be higher - function(itemScene){ - var vars = itemScene.vars; - return vars.row.size.height / 2 - vars.clientSize.height / 2; - } : - // Left align items of a same column - 0) - .lockMark('width', - isHorizontal ? - function(itemScene){ return itemScene.vars.clientSize.width; } : - - // The biggest child width of the column - function(/*itemScene*/){ return this.parent.width(); }) - .pvMark - .def("hidden", "false") - .fillStyle(function(){ // TODO: ?? - return this.hidden() == "true" ? - "rgba(200,200,200,1)" : - "rgba(200,200,200,0.0001)"; - }) - .cursor(function(itemScene){ - return itemScene.isClickable() ? "pointer" : null; - }) - .event("click", function(itemScene){ - if(itemScene.isClickable()){ - return itemScene.click(); - } - }) - ; - - // ROW > ITEM > MARKER - var pvLegendMarkerPanel = new pvc.visual.Panel(this, this.pvLegendPanel) - .pvMark - .left(0) - .top (0) - .right (null) - .bottom(null) - .width (function(itemScene){ return itemScene.vars.markerSize; }) - .height(function(itemScene){ return itemScene.vars.clientSize.height; }) - ; - - if(pvc.debug >= 20){ - pvLegendRowPanel.strokeStyle('red'); - this.pvLegendPanel.strokeStyle('green'); - pvLegendMarkerPanel.strokeStyle('blue'); - } - - /* RULE/MARKER */ - rootScene.childNodes.forEach(function(groupScene){ - var pvGroupPanel = new pvc.visual.Panel(this, pvLegendMarkerPanel) - .pvMark - .visible(function(itemScene){ - return itemScene.parent === groupScene; - }); - - groupScene.renderer().create(this, pvGroupPanel, groupScene.extensionPrefix, wrapper); - }, this); - - /* LABEL */ - this.pvLabel = new pvc.visual.Label(this, pvLegendMarkerPanel.anchor("right"), { - extensionId: 'label', - wrapper: wrapper - }) - .intercept('textStyle', function(itemScene) { - var baseTextStyle = this.delegateExtension() || "black"; - return itemScene.isOn() ? - baseTextStyle : - pvc.toGrayScale(baseTextStyle, null, undefined, 150); - }) - .pvMark - .textAlign('left') // panel type anchors don't adjust textAlign this way - .text(function(itemScene){ return itemScene.vars.value.label; }) - // -4 is to compensate for now the label being anchored to the panel instead of the rule or the dot... - .lock('textMargin', function(itemScene){ return itemScene.vars.textMargin - 4; }) - .font(function(itemScene){ return itemScene.vars.font; }) // TODO: lock? - .textDecoration(function(itemScene){ return itemScene.isOn() ? "" : "line-through"; }) - ; - }, - - _getExtensionId: function(){ - return 'area'; - }, - - _getExtensionPrefix: function(){ - return 'legend'; - }, - - _getSelectableMarks: function(){ - // Catches both the marker and the label. - // Also, if selection changes, renderInteractive re-renders these. - return [this.pvLegendPanel]; - }, - - _getBulletRootScene: function(){ - var rootScene = this._rootScene; - if(!rootScene){ - /* The legend root scene contains all datums of its chart */ - rootScene = new pvc.visual.legend.BulletRootScene(null, { - panel: this, - group: this.chart.data, - horizontal: this.isAnchorTopOrBottom(), - font: this.font, - markerSize: this.markerSize, - textMargin: this.textMargin, - itemPadding: this.itemPadding - }); - - this._rootScene = rootScene; - } - - return rootScene; - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcMetricPoint.js b/pacotes/ccc2/pvc/pvcMetricPoint.js deleted file mode 100755 index be09a55..0000000 --- a/pacotes/ccc2/pvc/pvcMetricPoint.js +++ /dev/null @@ -1,201 +0,0 @@ - -/** - * MetricPointAbstract is the base class of metric dot and line. - */ -def -.type('pvc.MetricPointAbstract', pvc.MetricXYAbstract) -.init(function(options){ - - this.base(options); - - var parent = this.parent; - if(parent) { - this._colorRole = parent._colorRole; - this._sizeRole = parent._sizeRole; - } -}) -.add({ - _initPlotsCore: function(){ - var pointPlot = this._createPointPlot(); - - var trend = pointPlot.option('Trend'); - if(trend){ - // Trend Plot - new pvc.visual.MetricPointPlot(this, { - name: 'trend', - fixed: { - DataPart: 'trend', - TrendType: 'none', - NullInterpolatioMode: 'none', - ColorRole: 'series', // one trend per series - SizeRole: null, - SizeAxis: null, - OrthoAxis: 1 - }, - defaults: { - ColorAxis: 2, - LinesVisible: true, - DotsVisible: false - } - }); - } - }, - - //_createPointPlot: function(){}, - - /* Required because of trends */ - _hasDataPartRole: function(){ - return true; - }, - - _getColorRoleSpec: function(){ - return { - //isMeasure: true, // TODO: not being set as measure when continuous... - defaultSourceRole: 'series', - defaultDimension: 'color*', - dimensionDefaults: { - valueType: Number - } - }; - }, - - /** - * Initializes each chart's specific roles. - * @override - */ - _initVisualRoles: function(){ - - this.base(); - - this._sizeRole = this._addVisualRole('size', { - isMeasure: true, - requireSingleDimension: true, - requireIsDiscrete: false, - defaultDimension: 'size', - dimensionDefaults: { - valueType: Number - } - }); - }, - - _getTranslationClass: function(translOptions){ - return def - .type(this.base(translOptions)) - .add(pvc.data.MetricPointChartTranslationOper); - }, - - _initData: function(keyArgs){ - - this.base(keyArgs); - - // Cached - var sizeGrouping = this._sizeRole.grouping; - if(sizeGrouping){ - this._sizeDim = this.data.dimensions(sizeGrouping.firstDimensionName()); - } - }, - - _collectPlotAxesDataCells: function(plot, dataCellsByAxisTypeThenIndex){ - - this.base(plot, dataCellsByAxisTypeThenIndex); - - /* NOTE: Cartesian axes are created even when hasMultiRole && !parent - * because it is needed to read axis options in the root chart. - * Also binding occurs to be able to know its scale type. - * Yet, their scales are not setup at the root level. - */ - - /* Configure Base Axis Data Cell */ - if(plot.type === 'scatter' && plot.option('DotsVisible')){ - - var sizeRoleName = plot.option('SizeRole'); - if(sizeRoleName){ - var sizeRole = this.visualRoles(sizeRoleName); - if(sizeRole.isBound()){ - var sizeDataCellsByAxisIndex = - def - .array - .lazy(dataCellsByAxisTypeThenIndex, 'size'); - - def - .array - .lazy(sizeDataCellsByAxisIndex, plot.option('SizeAxis') - 1) - .push({ - plot: plot, - role: this.visualRoles(plot.option('SizeRole')), - dataPartValue: plot.option('DataPart') - }); - } - } - } - }, - - _setAxesScales: function(hasMultiRole){ - - this.base(hasMultiRole); - - if(!hasMultiRole || this.parent){ - var sizeAxis = this.axes.size; - if(sizeAxis && sizeAxis.isBound()){ - this._createAxisScale(sizeAxis); - } - } - }, - - /** - * @override - */ - _createPlotPanels: function(parentPanel, baseOptions){ - // TODO: integrate these options in the MetricPointPlot or in the SizeAxis? - var options = this.options; - var panelOptions = def.set( - Object.create(baseOptions), - 'sizeAxisRatio', options.sizeAxisRatio, - 'sizeAxisRatioTo', options.sizeAxisRatioTo, - 'autoPaddingByDotSize', options.autoPaddingByDotSize); - - var scatterPlot = this.plots.scatter; - this.scatterChartPanel = // V1 property - new pvc.MetricPointPanel(this, parentPanel, scatterPlot, panelOptions); - - var trendPlot = this.plots.trend; - if(trendPlot){ - new pvc.MetricPointPanel( - this, - parentPanel, - trendPlot, - Object.create(panelOptions)); - } - }, - - defaults: { - axisOriginIsZero: false, - tooltipOffset: 10 - } -}); - -/** - * Metric Dot Chart - */ -def -.type('pvc.MetricDotChart', pvc.MetricPointAbstract) -.add({ - _createPointPlot: function(){ - return new pvc.visual.MetricPointPlot(this, { - fixed: {DotsVisible: true} - }); - } -}); - -/** - * Metric Line Chart - */ -def -.type('pvc.MetricLineChart', pvc.MetricPointAbstract) -.add({ - _createPointPlot: function(){ - return new pvc.visual.MetricPointPlot(this, { - fixed: {LinesVisible: true} - }); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcMetricPointPanel.js b/pacotes/ccc2/pvc/pvcMetricPointPanel.js deleted file mode 100755 index 2950f0e..0000000 --- a/pacotes/ccc2/pvc/pvcMetricPointPanel.js +++ /dev/null @@ -1,731 +0,0 @@ - -/* - * Metric Line/Dot panel. - * Class that draws dot and line plots. - * Specific options are: - * dotsVisible - Show or hide dots. Default: true - * linesVisible - Show or hide dots. Default: true - * valuesVisible - Show or hide line value. Default: false - * - * Has the following protovis extension points: - * - * chart_ - for the main chart Panel - * line_ - for the actual line - * linePanel_ - for the panel where the lines sit - * lineDot_ - the dots on the line - * lineLabel_ - for the main line label - */ -def -.type('pvc.MetricPointPanel', pvc.CartesianAbstractPanel) -.init(function(chart, parent, plot, options) { - - this.base(chart, parent, plot, options); - - this.axes.size = chart._getAxis('size', (plot.option('SizeAxis') || 0) - 1); // may be undefined - - var sizeRoleName = plot.option('SizeRole'); // assumed to be always defined - this.visualRoles.size = chart.visualRoles(sizeRoleName); - - this.linesVisible = plot.option('LinesVisible'); // TODO - this.dotsVisible = plot.option('DotsVisible' ); // TODO - if(!this.linesVisible && !this.dotsVisible){ - this.linesVisible = true; - plot.option.specify({'LinesVisible': true}); - } - - this.dotShape = plot.option('Shape'); - - if(!this.offsetPaddings){ - this.offsetPaddings = new pvc.Sides(0.01); - } -}) -.add({ - - pvLine: null, - pvDot: null, - pvLabel: null, - pvScatterPanel: null, - - dotShape: "circle", - - // Ratio of the biggest bubble diameter to - // the length of plot area dimension according to option 'sizeAxisRatioTo' - sizeAxisRatio: 1/5, - - sizeAxisRatioTo: 'minWidthHeight', // 'height', 'width', - - autoPaddingByDotSize: true, - - // Override default mappings - _v1DimRoleName: { - //'series': 'series', - 'category': 'x', - 'value': 'y' - }, - - _creating: function(){ - // Register BULLET legend prototype marks - var groupScene = this.defaultVisibleBulletGroupScene(); - if(groupScene && !groupScene.hasRenderer()){ - var colorAxis = groupScene.colorAxis; - var drawMarker = def.nullyTo(colorAxis.option('LegendDrawMarker', true), this.dotsVisible); - var drawRule = def.nullyTo(colorAxis.option('LegendDrawLine', true), this.linesVisible); - if(drawMarker || drawRule){ - var keyArgs = {}; - if((keyArgs.drawMarker = drawMarker)){ - keyArgs.markerShape = - colorAxis.option('LegendShape', true) || - 'circle'; // Dot's default shape - - keyArgs.markerPvProto = new pv.Dot() - .lineWidth(1.5, pvc.extensionTag) // act as if it were a user extension - .shapeSize(12, pvc.extensionTag); // idem - - this.extend(keyArgs.markerPvProto, 'dot', {constOnly: true}); - } - - if((keyArgs.drawRule = drawRule)){ - keyArgs.rulePvProto = new pv.Line() - .lineWidth(1.5, pvc.extensionTag); - - this.extend(keyArgs.rulePvProto, 'line', {constOnly: true}); - } - - groupScene.renderer( - new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs)); - } - } - }, - - _getRootScene: function(){ - var me = this; - var rootScene = me._rootScene; - if(!rootScene){ - var roles = me.visualRoles; - var hasColorRole = roles.color.isBound() && !me.axes.color.scale.isNull; - var hasSizeRole = roles.size .isBound() && !me.axes.size .scale.isNull; - - me._rootScene = - rootScene = me._buildScene(hasColorRole, hasSizeRole); - } - - return rootScene; - }, - - /* - * @override - */ - _calcLayout: function(layoutInfo){ - var rootScene = this._getRootScene(); - - /* Determine Dot Size Scale */ - if(rootScene.hasSizeRole){ - var areaRange = this._calcDotAreaRange(layoutInfo); - - this.sizeScale = this.axes.size - .setScaleRange(areaRange) - .scale; - } - - /* Adjust axis offset to avoid dots getting off the content area */ - this._calcAxesPadding(layoutInfo, rootScene); - }, - - _getDotDiameterRefLength: function(layoutInfo){ - // Use the border box to always have the same size for != axis offsets (paddings) - - var clientSize = layoutInfo.clientSize; - var paddings = layoutInfo.paddings; - - switch(this.sizeAxisRatioTo){ - case 'minWidthHeight': - return Math.min( - clientSize.width + paddings.width, - clientSize.height + paddings.height); - - case 'width': return clientSize.width + paddings.width ; - case 'height': return clientSize.height + paddings.height; - } - - if(pvc.debug >= 2){ - this._log( - def.format( - "Invalid option 'sizeAxisRatioTo' value. Assuming 'minWidthHeight'.", - [this.sizeAxisRatioTo])); - } - - this.sizeRatioTo = 'minWidthHeight'; - - return this._getDotDiameterRefLength(layoutInfo); - }, - - _calcDotRadiusRange: function(layoutInfo){ - var refLength = this._getDotDiameterRefLength(layoutInfo); - - // Diameter is 1/5 of ref length - var max = (this.sizeAxisRatio / 2) * refLength; - - // Minimum SIZE (not radius) is 12 - var min = Math.sqrt(12); - - return {min: min, max: max}; - }, - - _calcDotAreaRange: function(layoutInfo){ - - var radiusRange = this._calcDotRadiusRange(layoutInfo); - - // Diamond Adjustment - if(this.dotShape === 'diamond'){ - // Protovis draws diamonds inscribed on - // a square with half-side radius*Math.SQRT2 - // (so that diamonds just look like a rotated square) - // For the height/width of the diamondnot to exceed the cell size - // we compensate that factor here. - radiusRange.max /= Math.SQRT2; - radiusRange.min /= Math.SQRT2; - } - - var maxArea = radiusRange.max * radiusRange.max, - minArea = radiusRange.min * radiusRange.min, - areaSpan = maxArea - minArea; - - if(areaSpan <= 1){ - // Very little space - // Rescue Mode - show *something* - maxArea = Math.max(maxArea, 2); - minArea = 1; - areaSpan = maxArea - minArea; - - radiusRange = { - min: Math.sqrt(minArea), - max: Math.sqrt(maxArea) - }; - - if(pvc.debug >= 3){ - this._log("Using rescue mode dot area calculation due to insufficient space."); - } - } - - return { - min: minArea, - max: maxArea, - span: areaSpan - }; - }, - - _calcAxesPadding: function(layoutInfo, rootScene){ - // If we were not to take axes rounding padding effect - // into account, it could be as simple as: - // var offsetRadius = radiusRange.max + 6; - // requestPaddings = new pvc.Sides(offsetRadius); - - var requestPaddings; - - if(!this.autoPaddingByDotSize){ - requestPaddings = this._calcRequestPaddings(layoutInfo); - } else { - var axes = this.axes; - var clientSize = layoutInfo.clientSize; - var paddings = layoutInfo.paddings; - - requestPaddings = {}; - - /* The Worst case implementation would be like: - * Use more padding than is required in many cases, - * but ensures that no dot ever leaves the "stage". - * - * Half a circle must fit in the client area - * at any edge of the effective plot area - * (the client area minus axis offsets). - */ - - // X and Y axis orientations - axes.x.setScaleRange(clientSize.width ); - axes.y.setScaleRange(clientSize.height); - - // X and Y visual roles - var sceneXScale = axes.base .sceneScale({sceneVarName: 'x'}); - var sceneYScale = axes.ortho.sceneScale({sceneVarName: 'y'}); - - var xLength = axes.base .scale.max; - var yLength = axes.ortho.scale.max; - - var hasSizeRole = rootScene.hasSizeRole; - var sizeScale = this.sizeScale; - if(!hasSizeRole){ - // Use the dot default size - var defaultSize = def.number.as(this._getExtension('dot', 'shapeRadius'), 0); - if(defaultSize <= 0){ - defaultSize = def.number.as(this._getExtension('dot', 'shapeSize'), 0); - if(defaultSize <= 0){ - defaultSize = 12; - } - } else { - // Radius -> Size - defaultSize = defaultSize * defaultSize; - } - - sizeScale = def.fun.constant(defaultSize); - } - - // TODO: these padding requests do not take the resulting new scale into account - // and as such do not work exactly... - //var xMinPct = xScale(xDomain.min) / clientSize.width; - //var overflowLeft = (offsetRadius - xMinPct * (paddings.left + clientSize.width)) / (1 - xMinPct); - - requestPaddings = {}; - - // Resolve (not of PercentValue so cannot use pvc.Sides#resolve) - var op; - if(this.offsetPaddings){ - op = {}; - pvc.Sides.names.forEach(function(side){ - var len_a = pvc.BasePanel.orthogonalLength[side]; - op[side] = (this.offsetPaddings[side] || 0) * (clientSize[len_a] + paddings[len_a]); - }, this); - } - - // TODO: this seems to not be working on negative x, y values - var setSide = function(side, padding){ - if(op){ - padding += (op[side] || 0); - } - - if(padding < 0){ - padding = 0; - } - - var value = requestPaddings[side]; - if(value == null || padding > value){ - requestPaddings[side] = padding; - } - }; - - var processScene = function(scene){ - var x = sceneXScale(scene); - var y = sceneYScale(scene); - var r = Math.sqrt(sizeScale(hasSizeRole ? scene.vars.size.value : 0)); - - // How much overflow on each side? - setSide('left', r - x); - setSide('bottom', r - y); - setSide('right', x + r - xLength ); - setSide('top', y + r - yLength); - }; - - rootScene - .children() - .selectMany(function(seriesScene){ return seriesScene.childNodes; }) - .each(processScene); - } - - layoutInfo.requestPaddings = requestPaddings; - }, - - /** - * @override - */ - _createCore: function(/*layoutInfo*/){ - this.base(); - - var myself = this; - var chart = this.chart; - var rootScene = this._getRootScene(); - - this._finalizeScene(rootScene); - - // --------------- - // BUILD - - this.pvPanel.zOrder(1); // Above axes - - this.pvScatterPanel = new pvc.visual.Panel(this, this.pvPanel, { - extensionId: 'panel' - }) - .lock('data', rootScene.childNodes) - .pvMark - ; - - var wrapper; - if(this.compatVersion() <= 1){ - wrapper = function(v1f){ - return function(dotScene){ - var d = { - category: dotScene.vars.x.rawValue, - value: dotScene.vars.y.rawValue - }; - - // Compensate for the effect of intermediate scenes on mark's index - var pseudo = Object.create(this); - pseudo.index = dotScene.dataIndex; - return v1f.call(pseudo, d); - }; - }; - } - - // -- LINE -- - var isLineNoSelect = /*dotsVisible && */chart._canSelectWithFocusWindow(); - - var line = new pvc.visual.Line(this, this.pvScatterPanel, { - extensionId: 'line', - wrapper: wrapper, - noTooltip: false, - noHover: true, - noSelect: isLineNoSelect, - showsSelection: !isLineNoSelect - }) - /* Data */ - .lock('data', function(seriesScene){ return seriesScene.childNodes; }) - - .lock('visible', this.linesVisible) - - /* Position & size */ - .override('x', function(){ return this.scene.basePosition; }) - .override('y', function(){ return this.scene.orthoPosition; }) - ; - - this.pvLine = line.pvMark; - - // -- DOT -- - var dot = new pvc.visual.Dot(this, this.pvLine, { - extensionId: 'dot', - wrapper: wrapper, - activeSeriesAware: this.linesVisible - }) - .intercept('visible', function(){ - return !this.scene.isIntermediate && this.delegateExtension(true); - }) - .lock('shape', this.dotShape) - .override('x', function(){ return this.scene.basePosition; }) - .override('y', function(){ return this.scene.orthoPosition; }) - .override('color', function(type){ - /* - * Handle dotsVisible - * ----------------- - * Despite !dotsVisible, - * show a dot anyway when: - * 1) it is active, or - * 2) it is single (the only dot in the dataset) - */ - if(!myself.dotsVisible){ - var visible = this.scene.isActive || - this.scene.isSingle; - if(!visible) { - return pvc.invisibleFill; - } - } - - // Follow normal logic - return this.base(type); - }) - ; - - this.pvDot = dot.pvMark; - - this.pvDot.rubberBandSelectionMode = 'center'; - - // -- COLOR -- - dot - .override('defaultColor', function(type){ - var color = this.base(type); - - if(color && type === 'stroke'){ - color = color.darker(); - } - - // When no lines are shown, dots are shown with transparency, - // which helps in distinguishing overlapped dots. - // With lines shown, it would look strange. - // ANALYZER requirements, so until there's no way to configure it... - // TODO: this probably can now be done with ColorTransform -// if(!myself.linesVisible){ -// color = color.alpha(color.opacity * 0.85); -// } - - return color; - }) - .override('interactiveColor', function(color, type){ - if(type === 'stroke' && this.scene.isActive) { - // Don't make border brighter on active - return color; - } - - return this.base(color, type); - }) - ; - - // -- DOT SIZE -- - if(!rootScene.hasSizeRole){ - dot - .override('baseSize', function(){ - /* When not showing dots, - * but a datum is alone and - * wouldn't be visible using lines, - * show the dot anyway, - * with a size = to the line's width^2 - */ - if(!myself.dotsVisible) { - if(this.scene.isSingle) { - // Obtain the line Width of the "sibling" line - var lineWidth = Math.max(myself.pvLine.scene[this.pvMark.index].lineWidth, 0.2) / 2; - return lineWidth * lineWidth; - } - } - - return this.base(); - }); - } else { - var sizeAxis = myself.axes.size; - if (sizeAxis.scaleUsesAbs()) { - dot - .override('strokeColor', function () { - return this.scene.vars.size.value < 0 ? "#000000" : this.base(); - }) - .optional('lineCap', 'round') // only used by strokeDashArray - .optionalMark('strokeDasharray', function (scene){ - return scene.vars.size.value < 0 ? 'dot' : null; // . . . - }) - .optionalMark('lineWidth', function (scene){ - return scene.vars.size.value < 0 ? 1.8 : 1.5; - }) - ; - } - - var sizeScale = this.sizeScale; - - /* Ignore any extension */ - dot - .override('baseSize', function(){ - return sizeScale(this.scene.vars.size.value); - }) - .override('interactiveSize', function(size){ - if(this.scene.isActive){ - var radius = Math.sqrt(size) * 1.1; - return radius * radius; - } - - return size; - }) - ; - - // Default is to hide overflow dots, - // for a case where the provided offset, or calculated one is not enough - // (sizeAxisRatioTo='width' or 'height' don't guarantee no overflow) - // Padding area is used by the bubbles. - this.pvPanel.borderPanel.overflow("hidden"); - } - - // -- LABEL -- - if(this.valuesVisible){ - var extensionIds = ['label']; - if(this.compatVersion() <= 1){ - extensionIds.push('lineLabel'); - } - - this.pvLabel = new pvc.visual.Label( - this, - this.pvDot.anchor(this.valuesAnchor), - { - extensionId: extensionIds, - wrapper: wrapper - }) - .pvMark - .font(this.valuesFont) // default - .text(function(scene){ - return def.string.join(",", scene.vars.x.label, scene.vars.y.label); - }) - ; - } - }, - - /** - * Renders this.pvScatterPanel - the parent of the marks that are affected by interaction changes. - * @override - */ - renderInteractive: function(){ - this.pvScatterPanel.render(); - }, - - /** - * Returns an array of marks whose instances are associated to a datum or group, or null. - * @override - */ - _getSelectableMarks: function(){ - var marks = []; - - marks.push(this.pvDot); - - if(this.linesVisible){ - marks.push(this.pvLine); - } - - return marks; - }, - - _finalizeScene: function(rootScene){ - var axes = this.axes, - sceneBaseScale = axes.base.sceneScale ({sceneVarName: 'x'}), - sceneOrthoScale = axes.ortho.sceneScale({sceneVarName: 'y'}); - - rootScene - .children() - .selectMany(function(seriesScene){ return seriesScene.childNodes; }) - .each(function(leafScene){ - leafScene.basePosition = sceneBaseScale (leafScene); - leafScene.orthoPosition = sceneOrthoScale(leafScene); - }); - - return rootScene; - }, - - _buildScene: function(hasColorRole, hasSizeRole){ - var data = this.visibleData(); - - var rootScene = new pvc.visual.Scene(null, {panel: this, group: data}); - rootScene.hasColorRole = hasColorRole; - rootScene.hasSizeRole = hasSizeRole; - - var roles = this.visualRoles; - var colorVarHelper = new pvc.visual.RoleVarHelper(rootScene, roles.color, {forceUnbound: !hasColorRole}); - var sizeVarHelper = new pvc.visual.RoleVarHelper(rootScene, roles.size, {forceUnbound: !hasSizeRole }); - - var xDim = data.owner.dimensions(roles.x.firstDimensionName()); - var yDim = data.owner.dimensions(roles.y.firstDimensionName()); - - // -------------- - - /* Create starting scene tree */ - data.children() - .each(createSeriesScene, this); - - /** - * Update the scene tree to include intermediate leaf-scenes, - * to add in the creation of lines and areas. - */ - rootScene - .children() - .each(completeSeriesScenes, this); - - return rootScene; - - function createSeriesScene(seriesGroup){ - /* Create series scene */ - var seriesScene = new pvc.visual.Scene(rootScene, {group: seriesGroup}); - - seriesScene.vars.series = - pvc.visual.ValueLabelVar.fromComplex(seriesGroup); - - colorVarHelper.onNewScene(seriesScene, /* isLeaf */ false); - - seriesGroup - .datums() - .each(function(datum, dataIndex){ - var xAtom = datum.atoms[xDim.name]; - if(xAtom.value == null){ - return; - } - - var yAtom = datum.atoms[yDim.name]; - if(yAtom.value == null){ - return; - } - - /* Create leaf scene */ - var scene = new pvc.visual.Scene(seriesScene, {datum: datum}); - scene.dataIndex = dataIndex; - - scene.vars.x = Object.create(xAtom); - scene.vars.y = Object.create(yAtom); - - sizeVarHelper .onNewScene(scene, /* isLeaf */ true); - colorVarHelper.onNewScene(scene, /* isLeaf */ true); - - scene.isIntermediate = false; - }); - } - - function completeSeriesScenes(seriesScene) { - var seriesScenes = seriesScene.childNodes, - fromScene; - - /* As intermediate nodes are added, - * seriesScene.childNodes array is changed. - * - * The var 'toChildIndex' takes inserts into account; - * its value is always the index of 'toScene' in - * seriesScene.childNodes. - */ - for(var c = 0, /* category index */ - toChildIndex = 0, - pointCount = seriesScenes.length ; c < pointCount ; c++, toChildIndex++) { - - /* Complete toScene */ - var toScene = seriesScenes[toChildIndex]; - toScene.isSingle = !fromScene && !toScene.nextSibling; // Look ahead - - /* Possibly create intermediate scene - * (between fromScene and toScene) - */ - if(fromScene) { - var interScene = createIntermediateScene( - seriesScene, - fromScene, - toScene, - toChildIndex); - - if(interScene){ - toChildIndex++; - } - } - - // -------- - - fromScene = toScene; - } - } - - function createIntermediateScene( - seriesScene, - fromScene, - toScene, - toChildIndex){ - - /* Code for single, continuous and date/numeric dimensions - * Calls corresponding dimension's cast to ensure we have a date object, - * when that's the dimension value type. - */ - var interYValue = yDim.type.cast.call(null, ((+toScene.vars.y.value) + (+fromScene.vars.y.value)) / 2); - var interXValue = xDim.type.cast.call(null, ((+toScene.vars.x.value) + (+fromScene.vars.x.value)) / 2); - - //---------------- - - var interScene = new pvc.visual.Scene(seriesScene, { - /* insert immediately before toScene */ - index: toChildIndex, - datum: toScene.datum - }); - - interScene.dataIndex = toScene.dataIndex; - - interScene.vars.x = new pvc.visual.ValueLabelVar( - interXValue, - xDim.format(interXValue), - interXValue); - - interScene.vars.y = new pvc.visual.ValueLabelVar( - interYValue, - yDim.format(interYValue), - interYValue); - - sizeVarHelper .onNewScene(interScene, /* isLeaf */ true); - colorVarHelper.onNewScene(interScene, /* isLeaf */ true); - - interScene.ownerScene = toScene; - interScene.isIntermediate = true; - interScene.isSingle = false; - - return interScene; - } - } -}); diff --git a/pacotes/ccc2/pvc/pvcMetricXYAbstract.js b/pacotes/ccc2/pvc/pvcMetricXYAbstract.js deleted file mode 100755 index bb7cfef..0000000 --- a/pacotes/ccc2/pvc/pvcMetricXYAbstract.js +++ /dev/null @@ -1,147 +0,0 @@ - -/** - * MetricXYAbstract is the base class of metric XY charts. - * (Metric stands for: - * Measure, Continuous or Not-categorical base and ortho axis) - */ -def -.type('pvc.MetricXYAbstract', pvc.CartesianAbstract) -.init(function(options){ - - this.base(options); - - var parent = this.parent; - if(parent) { - this._xRole = parent._xRole; - this._yRole = parent._yRole; - } -}) -.add({ - _processOptionsCore: function(options){ - - this.base(options); - - // Has no meaning in this chart type - // Only used by discrete scales - options.panelSizeRatio = 1; - }, - - /** - * Initializes each chart's specific roles. - * @override - */ - _initVisualRoles: function(){ - - this.base(); - - this._xRole = this._addVisualRole('x', { - isMeasure: true, - isRequired: true, - requireSingleDimension: true, - requireIsDiscrete: false, - defaultDimension: 'x', - dimensionDefaults: { - valueType: this.options.timeSeries ? Date : Number - } - }); - - this._yRole = this._addVisualRole('y', { - isMeasure: true, - isRequired: true, - requireSingleDimension: true, - requireIsDiscrete: false, - defaultDimension: 'y', - dimensionDefaults: { - valueType: Number - } - }); - }, - - _initData: function(){ - this.base.apply(this, arguments); - - // Cached - this._xDim = this.data.dimensions(this._xRole.firstDimensionName()); - this._yDim = this.data.dimensions(this._yRole.firstDimensionName()); - }, - - _generateTrendsDataCellCore: function(newDatums, dataCell, trendInfo){ - var serRole = this._serRole; - var xRole = this._xRole; - var yRole = dataCell.role; - var trendOptions = dataCell.trend; - - this._warnSingleContinuousValueRole(yRole); - - var dataPartDimName = this._dataPartRole.firstDimensionName(); - var xDimName = xRole.firstDimensionName(); - var yDimName = yRole.firstDimensionName(); - - // Visible part data, possibly grouped by series (if series is bound) - var data = this.visibleData(dataCell.dataPartValue); - - // For each series... - def - .scope(function(){ - return serRole.isBound() ? - data.children() : // data already only contains visible data - def.query([data]) // null series - ; - }) - .each(genSeriesTrend, this) - ; - - function genSeriesTrend(serData){ - var funX = function(datum){ - return datum.atoms[xDimName].value; - }; - - var funY = function(datum){ - return datum.atoms[yDimName].value; - }; - - var datums = - serData - .datums() - .sort(null, /* by */funX) - .array(); - - var options = def.create(trendOptions, { - rows: def.query(datums), - x: funX, - y: funY - }); - - var trendModel = trendInfo.model(options); - if(trendModel){ - - // If a label has already been registered, it is preserved... (See BaseChart#_fixTrendsLabel) - var dataPartAtom = data.owner - .dimensions(dataPartDimName) - .intern(this.root._firstTrendAtomProto); - - datums.forEach(function(datum, index){ - var trendX = funX(datum); - if(trendX){ - var trendY = trendModel.sample(trendX, funY(datum), index); - if(trendY != null){ - var atoms = - def.set( - Object.create(serData.atoms), // just common atoms - xDimName, trendX, - yDimName, trendY, - dataPartDimName, dataPartAtom); - - newDatums.push( - def.set( - new pvc.data.Datum(data.owner, atoms), - 'isVirtual', true, - 'isTrend', true, - 'trendType', trendInfo.type)); - } - } - }); - } - } - } -}); diff --git a/pacotes/ccc2/pvc/pvcMultiChartPanel.js b/pacotes/ccc2/pvc/pvcMultiChartPanel.js deleted file mode 100755 index 009eddf..0000000 --- a/pacotes/ccc2/pvc/pvcMultiChartPanel.js +++ /dev/null @@ -1,538 +0,0 @@ - -def -.type('pvc.MultiChartPanel', pvc.BasePanel) -.add({ - anchor: 'fill', - _multiInfo: null, - - createSmallCharts: function(){ - var chart = this.chart; - var options = chart.options; - - /* I - Determine how many small charts to create */ - - // multiChartMax can be Infinity - var multiChartMax = Number(options.multiChartMax); - if(isNaN(multiChartMax) || multiChartMax < 1) { - multiChartMax = Infinity; - } - - var multiChartRole = chart.visualRoles('multiChart'); - var data = chart.data.flattenBy(multiChartRole, {visible: true}); - var leafCount = data._children.length; - var count = Math.min(leafCount, multiChartMax); - if(count === 0) { - // Shows no message to the user. - // An empty chart, like when all series are hidden through the legend. - return; - } - - /* II - Determine basic layout (row and col count) */ - - // multiChartColumnsMax can be Infinity - var multiChartColumnsMax = +options.multiChartColumnsMax; // to number - if(isNaN(multiChartColumnsMax) || multiChartMax < 1) { - multiChartColumnsMax = 3; - } - - var colCount = Math.min(count, multiChartColumnsMax); - // - /*jshint expr:true */ - colCount >= 1 && isFinite(colCount) || def.assert("Must be at least 1 and finite"); - // - - var rowCount = Math.ceil(count / colCount); - // - /*jshint expr:true */ - rowCount >= 1 || def.assert("Must be at least 1"); - // - - /* III - Determine if axes need coordination (null if no coordination needed) */ - - var coordRootAxesByScopeType = this._getCoordinatedRootAxesByScopeType(); - var coordScopesByType, addChartToScope, indexChartByScope; - if(coordRootAxesByScopeType){ - coordScopesByType = {}; - - // Each scope is a specific - // 'row', 'column' or the single 'global' scope - addChartToScope = function(childChart, scopeType, scopeIndex){ - var scopes = def.array.lazy(coordScopesByType, scopeType); - - def.array.lazy(scopes, scopeIndex).push(childChart); - }; - - indexChartByScope = function(childChart){ - // Index child charts by scope - // on scopes having axes requiring coordination. - if(coordRootAxesByScopeType.row){ - addChartToScope(childChart, 'row', childChart.smallRowIndex); - } - - if(coordRootAxesByScopeType.column){ - addChartToScope(childChart, 'column', childChart.smallColIndex); - } - - if(coordRootAxesByScopeType.global){ - addChartToScope(childChart, 'global', 0); - } - }; - } - - /* IV - Create and _preRender small charts */ - var childOptionsBase = this._buildSmallChartsBaseOptions(); - var ChildClass = chart.constructor; - for(var index = 0 ; index < count ; index++) { - var childData = data._children[index]; - - var colIndex = (index % colCount); - var rowIndex = Math.floor(index / colCount); - var childOptions = def.set( - Object.create(childOptionsBase), - 'smallColIndex', colIndex, - 'smallRowIndex', rowIndex, - 'title', childData.absLabel, // does not change with trends - 'data', childData); - - var childChart = new ChildClass(childOptions); - - if(!coordRootAxesByScopeType){ - childChart._preRender(); - } else { - // options, data, plots, axes, - // trends, interpolation, axes_scales - childChart._preRenderPhase1(); - - indexChartByScope(childChart); - } - } - - // Need _preRenderPhase2? - if(coordRootAxesByScopeType){ - // For each scope type having scales requiring coordination - // find the union of the scales' domains for each - // scope instance - // Finally update all scales of the scope to have the - // calculated domain. - def.eachOwn(coordRootAxesByScopeType, function(axes, scopeType){ - axes.forEach(function(axis){ - - coordScopesByType[scopeType] - .forEach(function(scopeCharts){ - this._coordinateScopeAxes(axis.id, scopeCharts); - }, this); - - }, this); - }, this); - - // Finalize _preRender, now that scales are coordinated - chart.children.forEach(function(childChart){ - childChart._preRenderPhase2(); - }); - } - - // By now, trends and interpolation - // have updated the data's with new Datums, if any. - - this._multiInfo = { - data: data, - count: count, - rowCount: rowCount, - colCount: colCount, - multiChartColumnsMax: multiChartColumnsMax, - coordScopesByType: coordScopesByType - }; - }, - - _getCoordinatedRootAxesByScopeType: function(){ - // Index axes that need to be coordinated, by scopeType - var hasCoordination = false; - var rootAxesByScopeType = - def - .query(this.chart.axesList) - .multipleIndex(function(axis){ - if(axis.scaleType !== 'discrete' && // Not implemented (yet...) - axis.option.isDefined('DomainScope')){ - - var scopeType = axis.option('DomainScope'); - if(scopeType !== 'cell'){ - hasCoordination = true; - return scopeType; - } - } - }) - ; - - return hasCoordination ? rootAxesByScopeType : null; - }, - - _coordinateScopeAxes: function(axisId, scopeCharts){ - var unionExtent = - def - .query(scopeCharts) - .select(function(childChart){ - var scale = childChart.axes[axisId].scale; - if(!scale.isNull){ - var domain = scale.domain(); - return {min: domain[0], max: domain[1]}; - } - }) - .reduce(pvc.unionExtents, null) - ; - - if(unionExtent){ - // Fix the scale domain of every scale. - scopeCharts.forEach(function(childChart){ - var axis = childChart.axes[axisId]; - var scale = axis.scale; - if(!scale.isNull){ - scale.domain(unionExtent.min, unionExtent.max); - - axis.setScale(scale); // force update of dependent info. - } - }); - } - }, - - _buildSmallChartsBaseOptions: function(){ - // All size-related information is only supplied later in #_createCore. - var chart = this.chart; - var options = chart.options; - return def.set( - Object.create(options), - 'parent', chart, - 'legend', false, - 'titleFont', options.smallTitleFont, - 'titlePosition', options.smallTitlePosition, - 'titleAlign', options.smallTitleAlign, - 'titleAlignTo', options.smallTitleAlignTo, - 'titleOffset', options.smallTitleOffset, - 'titleKeepInBounds', options.smallTitleKeepInBounds, - 'titleMargins', options.smallTitleMargins, - 'titlePaddings', options.smallTitlePaddings, - 'titleSize', options.smallTitleSize, - 'titleSizeMax', options.smallTitleSizeMax); - }, - - /** - *

- * Implements small multiples chart layout. - * Currently, it's essentially a flow-layout, - * from left to right and then top to bottom. - *

- * - *

- * One small multiple chart is generated per unique combination - * of the values of the 'multiChart' visual role. - *

- * - *

- * The option "multiChartMax" is the maximum number of small charts - * that can be laid out. - * - * This can be useful if the chart's size cannot grow or - * if it cannot grow too much. - * - * Pagination can be implemented with the use of this and - * the option 'multiChartPageIndex', to allow for effective printing of - * small multiple charts. - *

- * - *

- * The option "multiChartPageIndex" is the desired page index. - * This option requires that "multiChartMax" is also specified with - * a finite and >= 1 value. - * - * After a render is performed, - * the chart properties - * {@link pvc.BaseChart#multiChartPageCount} and - * {@link pvc.BaseChart#multiChartPageIndex} will have been updated. - *

- * - *

- * The option 'multiChartColumnsMax' is the - * maximum number of charts that can be laid out in a row. - * The default value is 3. - * - * The value +Infinity can be specified, - * in which case there is no direct limit on the number of columns. - * - * If the width of small charts does not fit in the available width - * then the chart's width is increased. - *

- *

- * The option 'smallWidth' can be specified to fix the width, - * of each small chart, in pixels or, in string "1%" format, - * as a percentage of the available width. - * - * When not specified, but the option "multiChartColumnsMax" is specified and finite, - * the width of the small charts is the available width divided - * by the maximum number of charts in a row that actually occur - * (so that if there are less small charts than - * the maximum that can be placed on a row, - * these, nevertheless, take up the whole width). - * - * When both the options "smallWidth" and "multiChartColumnsMax" - * are unspecified, then the behavior is the same as if - * the value "33%" had been specified for "smallWidth": - * 3 charts will fit in the chart's initially specified width, - * yet the chart's width can grow to accommodate for further small charts. - *

- *

- * The option "multiChartSingleRowFillsHeight" affects the - * determination of the small charts height for the case where a single - * row exists. - * When the option is true, or unspecified, and a single row exists, - * the height of the small charts will be all the available height, - * looking similar to a non-multi-chart version of the same chart. - * When the option is false, - * the determination of the small charts height does not depend - * on the number of rows, and proceeds as follows. - *

- *

- * If the layout results in more than one row or - * when "multiChartSingleRowFillsHeight" is false, - * the height of the small charts is determined using the option - * 'smallAspectRatio', which is, by definition, width / height. - * A typical aspect ratio value would be 5/4, 4/3 or the golden ratio (~1.62). - * - * When the option is unspecified, - * a suitable value is determined, - * using internal heuristic methods - * that generally depend on the concrete chart type - * and specified options. - * - * No effort is made to fill all the available height. - * The layout can result in two rows that occupy only half of the - * available height. - * If the layout is such that the available height is exceeded, - * then the chart's height is increased. - *

- *

- * The option 'margins' can be specified to control the - * spacing between small charts. - * The default value is "2%". - * Margins are only applied between small charts: - * the outer margins of border charts are always 0. - *

- *

The option 'paddings' is applied to each small chart.

- * - * ** Orthogonal scroll bar on height/width overflow?? - * ** Legend vertical center on page height ?? Dynamic? - * - * @override - */ - _calcLayout: function(layoutInfo){ - var multiInfo = this._multiInfo; - if(!multiInfo){ - return; - } - - var chart = this.chart; - var options = chart.options; - var clientSize = layoutInfo.clientSize; - - // TODO - multi-chart pagination -// var multiChartPageIndex; -// if(isFinite(multiChartMax)) { -// multiChartPageIndex = chart.multiChartPageIndex; -// if(isNaN(multiChartPageIndex)){ -// multiChartPageIndex = null; -// } else { -// // The next page number -// // Initially, the chart property must have -1 to start iterating. -// multiChartPageIndex++; -// } -// } - - var prevLayoutInfo = layoutInfo.previous; - var initialClientWidth = prevLayoutInfo ? prevLayoutInfo.initialClientWidth : clientSize.width ; - var initialClientHeight = prevLayoutInfo ? prevLayoutInfo.initialClientHeight : clientSize.height; - - var smallWidth = pvc.PercentValue.parse(options.smallWidth); - if(smallWidth != null){ - smallWidth = pvc.PercentValue.resolve(smallWidth, initialClientWidth); - } - - var smallHeight = pvc.PercentValue.parse(options.smallHeight); - if(smallHeight != null){ - smallHeight = pvc.PercentValue.resolve(smallHeight, initialClientHeight); - } - - var ar = +options.smallAspectRatio; // + is to number - if(isNaN(ar) || ar <= 0){ - ar = this._calulateDefaultAspectRatio(); - } - - if(smallWidth == null){ - if(isFinite(multiInfo.multiChartColumnsMax)){ - // Distribute currently available client width by the effective max columns. - smallWidth = clientSize.width / multiInfo.colCount; - } else { - // Single Row - // Chart grows in width as needed - if(smallHeight == null){ - // Both null - // Height uses whole height - smallHeight = initialClientHeight; - } - - // Now use aspect ratio to calculate width - smallWidth = ar * smallHeight; - } - } - - if(smallHeight == null){ - if((multiInfo.rowCount === 1 && def.get(options, 'multiChartSingleRowFillsHeight', true)) || - (multiInfo.colCount === 1 && def.get(options, 'multiChartSingleColFillsHeight', true))){ - - // Height uses whole height - smallHeight = initialClientHeight; - } else { - smallHeight = smallWidth / ar; - } - } - - // ---------------------- - - def.set( - layoutInfo, - 'initialClientWidth', initialClientWidth, - 'initialClientHeight', initialClientHeight, - 'width', smallWidth, - 'height', smallHeight); - - return { - width: smallWidth * multiInfo.colCount, - height: Math.max(clientSize.height, smallHeight * multiInfo.rowCount) // vertical align center: pass only: smallHeight * multiInfo.rowCount - }; - }, - - _calulateDefaultAspectRatio: function(/*totalWidth*/){ - if(this.chart instanceof pvc.PieChart){ - // 5/4 <=> 10/8 < 10/7 - return 10/7; - } - - // Cartesian, ... - return 5/4; - - // TODO: this is not working well horizontal bar charts, for example -// var chart = this.chart; -// var options = chart.options; -// var chromeHeight = 0; -// var chromeWidth = 0; -// var defaultBaseSize = 0.4; -// var defaultOrthoSize = 0.2; -// -// // Try to estimate "chrome" of small chart -// if(chart instanceof pvc.CartesianAbstract){ -// var isVertical = chart.isOrientationVertical(); -// var size; -// if(options.showXScale){ -// size = parseFloat(options.xAxisSize || -// (isVertical ? options.baseAxisSize : options.orthoAxisSize) || -// options.axisSize); -// if(isNaN(size)){ -// size = totalWidth * (isVertical ? defaultBaseSize : defaultOrthoSize); -// } -// -// chromeHeight += size; -// } -// -// if(options.showYScale){ -// size = parseFloat(options.yAxisSize || -// (isVertical ? options.orthoAxisSize : options.baseAxisSize) || -// options.axisSize); -// if(isNaN(size)){ -// size = totalWidth * (isVertical ? defaultOrthoSize : defaultBaseSize); -// } -// -// chromeWidth += size; -// } -// } -// -// var contentWidth = Math.max(totalWidth - chromeWidth, 10); -// var contentHeight = contentWidth / this._getDefaultContentAspectRatio(); -// -// var totalHeight = chromeHeight + contentHeight; -// -// return totalWidth / totalHeight; - }, - -// _getDefaultContentAspectRatio: function(){ -// if(this.chart instanceof pvc.PieChart){ -// // 5/4 <=> 10/8 < 10/7 -// return 10/7; -// } -// -// // Cartesian -// return 5/2; -// }, - - _getExtensionId: function(){ - return 'content'; - }, - - _createCore: function(li){ - var mi = this._multiInfo; - if(!mi){ - // Empty - return; - } - - var chart = this.chart; - var options = chart.options; - - var smallMargins = options.smallMargins; - if(smallMargins == null){ - smallMargins = new pvc.Sides(new pvc.PercentValue(0.02)); - } else { - smallMargins = new pvc.Sides(smallMargins); - } - - var smallPaddings = new pvc.Sides(options.smallPaddings); - - chart.children.forEach(function(childChart){ - childChart._setSmallLayout({ - left: childChart.smallColIndex * li.width, - top: childChart.smallRowIndex * li.height, - width: li.width, - height: li.height, - margins: this._buildSmallMargins(childChart, smallMargins), - paddings: smallPaddings - }); - }, this); - - var coordScopesByType = mi.coordScopesByType; - if(coordScopesByType){ - chart._coordinateSmallChartsLayout(coordScopesByType); - } - - this.base(li); // calls _create on child chart's basePanel - }, - - _buildSmallMargins: function(childChart, smallMargins){ - var mi = this._multiInfo; - var lastColIndex = mi.colCount - 1; - var lastRowIndex = mi.rowCount - 1; - var colIndex = childChart.smallColIndex; - var rowIndex = childChart.smallRowIndex; - - var margins = {}; - if(colIndex > 0){ - margins.left = smallMargins.left; - } - if(colIndex < lastColIndex){ - margins.right = smallMargins.right; - } - if(rowIndex > 0){ - margins.top = smallMargins.top; - } - if(rowIndex < lastRowIndex){ - margins.bottom = smallMargins.bottom; - } - - return margins; - } -}); diff --git a/pacotes/ccc2/pvc/pvcNormalizedBarChart.js b/pacotes/ccc2/pvc/pvcNormalizedBarChart.js deleted file mode 100755 index 6f07dae..0000000 --- a/pacotes/ccc2/pvc/pvcNormalizedBarChart.js +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * A NormalizedBarChart is a 100% stacked bar chart. - */ -def -.type('pvc.NormalizedBarChart', pvc.BarAbstract) -.add({ - - /** - * Processes options after user options and default options have been merged. - * @override - */ - _processOptionsCore: function(options){ - // Still affects default data cell settings - options.stacked = true; - - this.base(options); - }, - - /** - * @override - */ - _getContinuousVisibleExtentConstrained: function(axis, min, max){ - if(axis.type === 'ortho') { - /* - * Forces showing 0-100 in the axis. - * Note that the bars are stretched automatically by the band layout, - * so this scale ends up being ignored by the bars. - * Note also that each category would have a different scale, - * so it isn't possible to provide a single correct scale, - * that would satisfy all the bars... - */ - return {min: 0, max: 100, minLocked: true, maxLocked: true}; - } - - return this.base(axis, min, max); - }, - - _initPlotsCore: function(hasMultiRole){ - - new pvc.visual.NormalizedBarPlot(this); - }, - - /* @override */ - _createPlotPanels: function(parentPanel, baseOptions){ - var barPlot = this.plots.bar; - - this.barChartPanel = - new pvc.NormalizedBarPanel( - this, - parentPanel, - barPlot, - Object.create(baseOptions)); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcNormalizedBarPanel.js b/pacotes/ccc2/pvc/pvcNormalizedBarPanel.js deleted file mode 100755 index 9774bfa..0000000 --- a/pacotes/ccc2/pvc/pvcNormalizedBarPanel.js +++ /dev/null @@ -1,11 +0,0 @@ - -/** - * Normalized Bar Panel. - */ -def -.type('pvc.NormalizedBarPanel', pvc.BarAbstractPanel) -.add({ - _barVerticalMode: function(){ - return 'expand'; - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcParallelCoordinates.js b/pacotes/ccc2/pvc/pvcParallelCoordinates.js deleted file mode 100755 index ff850d2..0000000 --- a/pacotes/ccc2/pvc/pvcParallelCoordinates.js +++ /dev/null @@ -1,600 +0,0 @@ - -/** - * Parallel coordinates offer a way to visualize data and make (sub-)selections - * on this dataset. - * This code has been based on a protovis example: - * http://vis.stanford.edu/protovis/ex/cars.html - */ -def -.type('pvc.ParallelCoordinates', pvc.BaseChart) -.init(function(options){ - - // Force the value dimension not to be a number - options = options || {}; - options.dimensions = options.dimensions || {}; - if(!options.dimensions.value) { - options.dimensions.value = {valueType: null}; - } - - this.base(options); -}) -.add({ - - parCoordPanel : null, - - _preRenderContent: function(contentOptions){ - this.parCoordPanel = new pvc.ParCoordPanel(this, this.basePanel, def.create(contentOptions, { - topRuleOffset : this.options.topRuleOffset, - botRuleOffset : this.options.botRuleOffset, - leftRuleOffset : this.options.leftRuleOffset, - rightRuleOffset : this.options.rightRuleOffset, - sortCategorical : this.options.sortCategorical, - mapAllDimensions : this.options.mapAllDimensions, - numDigits : this.options.numDigits - })); - }, - - defaults: def.create(pvc.BaseChart.prototype.defaults, { - compatVersion: 1, - - topRuleOffset: 30, - botRuleOffset: 30, - leftRuleOffset: 60, - rightRuleOffset: 60, - // sort the categorical (non-numerical dimensions) - sortCategorical: true, - // map numerical dimension too (uniform (possible non-linear) - // distribution of the observed values) - mapAllDimensions: true, - // number of digits after decimal point. - numDigits: 0 - }) -}); - -/* - * ParCoord chart panel. Generates a serie of Parallel Coordinate axis - * and allows you too make selections on these parallel coordinates. - * The selection will be stored in java-script variables and can be - * used as part of a where-clause in a parameterized SQL statement. - * Specific options are: - * << to be filled in >> - - * Has the following protovis extension points: - * - * chart_ - for the main chart Panel - * parCoord_ - for the parallel coordinates - * << to be completed >> - */ -def -.type('pvc.ParCoordPanel', pvc.BasePanel) -.add({ - anchor: 'fill', - pvParCoord: null, - - dimensions: null, - dimensionDescr: null, - - data: null, - - /***** - * retrieve the data from database and transform it to maps. - * - this.dimensions: all dimensions - * - this.dimensionDescr: description of dimensions - * - this.data: array with hashmap per data-point - *****/ - retrieveData: function () { - var data = this.chart.data; - var numDigit = this.chart.options.numDigits; - - this.dimensions = data.getVisibleCategories(); - var values = data.getValues(); - - var dataRowIndex = data.getVisibleSeriesIndexes(); - var pCoordIndex = data.getVisibleCategoriesIndexes(); - - var pCoordKeys = data.getCategories(); - - /****** - * Generate a Coordinate mapping. - * This mapping is required for categorical dimensions and - * optional for the numerical dimensions (in 4 steps) - ********/ - // 1: generate an array of coorMapping-functions - // BEWARE: Only the first row (index 0) is used to test whether - // a dimension is categorical or numerical! - var pCoordMapping = this.chart.options.mapAllDimensions ? - pCoordIndex.map(function(d) { - return isNaN(values[d][0]) ? - {categorical: true, len: 0, map: [] } : - {categorical: false, len: 0, map: [], displayValue: [] }; - }) : - pCoordIndex.map(function(d) { - return isNaN(values[d][0]) ? - {categorical: true, len: 0, map: [] } : - null; - }) - ; - - // 2: and generate a helper-function to update the mapping - // For non-categorical value the original-value is store in displayValue - var coordMapUpdate = function(i, val) { - var cMap = pCoordMapping[i]; - var k = null; // define in outer scope. - if (!cMap.categorical) { - var keyVal = val.toFixed(numDigit); // force the number to be a string - k = cMap.map[keyVal]; - if (k == null) { - k = cMap.len; - cMap.len++; - cMap.map[keyVal] = k; - cMap.displayValue[keyVal] = val; - } - } else { - k = cMap.map[val]; - if (k == null) { - k = cMap.len; - cMap.len++; - cMap.map[val] = k; - } - } - return k; - }; - - // 3. determine the value to be displayed - // for the categorical dimensions map == displayValue - for(var d in pCoordMapping){ - if (pCoordMapping.hasOwnProperty(d) && - pCoordMapping[d] && - pCoordMapping[d].categorical) { - pCoordMapping[d].displayValue = pCoordMapping[d].map; - } - } - - var i, item, k; - - // 4. apply the sorting of the dimension - if (this.chart.options.sortCategorical || - this.chart.options.mapAllDimensions) { - // prefill the coordMapping in order to get it in sorted order. - // sorting is required if all dimensions are mapped!! - for (i=0; i1)? elements[1] : ""; - return item2; - }); - - // 2. compute the min, max and step(-size) per dimension) - for(i=0; i theMax) { - theMax2 = theMax; - theMax = v; - } - } - } else { // no coordinate mapping applied - theMin = theMax = theMin2 = theMax2 = values[index][0]; - - for(k=1; k theMax) { - theMax2 = theMax; - theMax = v; - } - } - } // end else: coordinate mapping applied - - var theStep = ((theMax - theMax2) + (theMin2-theMin))/2; - item.min = theMin; - item.max = theMax; - item.step = theStep; - - // 3. and include the mapping (and reverse mapping) - item.categorical = false; - if (pCoordMapping[index]) { - item.map = pCoordMapping[index].map; - item.mapLength = pCoordMapping[index].len; - item.categorical = pCoordMapping[index].categorical; - - // create the reverse-mapping from key to original value - if (!item.categorical) { - item.orgValue = []; - var theMap = pCoordMapping[index].map; - for (var key in theMap){ - if(theMap.hasOwnProperty(key)){ - item.orgValue[ theMap[key] ] = 0.0+key; - } - } - } - } - } - - // generate a object using the given set of keys and values - // (map from keys[i] to vals[i]) - var genKeyVal = function (keys, vals) { - var record = {}; - for (var i = 0; i= filter[t].min) && (val <= filter[t].max); - }); - } : - function(d) { - return dims.every(function(t) { - // TO DO: check whether this operates correctly for - // categorical dimensions (when mapAllDimensions == false - return (d[t] >= filter[t].min) && (d[t] <= filter[t].max); - }); - } - ; - - /***** - * generateLinePattern produces a line pattern based on - * 1. the current dataset. - * 2. the current filter settings. - * 3. the provided colorMethod. - * The result is an array where each element contains at least - * {x1, y1, x2, y2, color} - * Two auxiliary fields are - * Furthermore auxiliary functions are provided - * - colorFuncFreq - * - colorFuncActive - *******/ - var auxData = null; - - /***** - * Draw the chart and its annotations (except dynamic content) - * ******/ - // Draw the data to the parallel dimensions - // (the light grey dataset is a fixed background) - this.pvParCoord = this.pvPanel.add(pv.Panel) - .data(myself.data) - .visible(selectVisible) - .add(pv.Line) - .data(dims) - .left(function(t, d) { return x(t); } ) - .bottom(function(t, d) { - var res = y[t] (d[t]); - return res; - }) - .strokeStyle("#ddd") - .lineWidth(1) - .antialias(false) - ; - - // Rule per dimension. - var rule = this.pvPanel.add(pv.Rule) - .data(dims) - .left(x) - .top(topRuleOffs) - .bottom(botRuleOffs) - ; - - // Dimension label - rule.anchor("top").add(pv.Label) - .top(labelTopOffs) - .font("bold 10px sans-serif") - .text(function(d) { return dimDescr[d].name; }) - ; - - // add labels on the categorical dimension - // compute the array of labels - var labels = []; - var labelXoffs = 6, - labelYoffs = 3; - for(var d in dimDescr) { - if(dimDescr.hasOwnProperty(d)){ - var dim = dimDescr[d]; - if (dim.categorical) { - var xVal = x(dim.id) + labelXoffs; - for (var l in dim.map){ - if(dim.map.hasOwnProperty(l)){ - labels[labels.length] = { - x: xVal, - y: y[dim.id](dim.map[l]) + labelYoffs, - label: l - }; - } - } - } - } - } - - var dimLabels = this.pvPanel.add(pv.Panel) - .data(labels) - .add(pv.Label) - .left(function(d) {return d.x;}) - .bottom(function(d) { return d.y;}) - .text(function(d) { return d.label;}) - .textAlign("left") - ; - - - /***** - * Add an additional panel over the top for the dynamic content - * (and draw the (full) dataset) - *******/ - // Draw the selected (changeable) data on a new panel on top - var change = this.pvPanel.add(pv.Panel); - var line = change.add(pv.Panel) - .data(myself.data) - .visible(selectVisible) - .add(pv.Line) - .data(dims) - .left(function(t, d) { return x(t);}) - .bottom(function(t, d) { return y[t](d[t]); }) - .strokeStyle(function(t, d) { - var dd = dimDescr[active]; - var val = (dd.orgValue && !dd.categorical) ? - dd.orgValue[ d[active] ] : - d[active] - ; - return colors[active](val); - }) - .lineWidth(1) - ; - - /***** - * Add the user-interaction (mouse-interface) - * and the (dynamic) labels of the selection. - *******/ - - // Updater for slider and resizer. - function update(d) { - var t = d.dim; - filter[t].min = Math.max(y[t].domain()[0], y[t].invert(height - d.y - d.dy)); - filter[t].max = Math.min(y[t].domain()[1], y[t].invert(height - d.y)); - active = t; - change.render(); - return false; - } - - // Updater for slider and resizer. - function selectAll(d) { - if (d.dy < 3) { // - var t = d.dim; - filter[t].min = Math.max(y[t].domain()[0], y[t].invert(0)); - filter[t].max = Math.min(y[t].domain()[1], y[t].invert(height)); - d.y = botRuleOffs; d.dy = ruleHeight; - active = t; - change.render(); - } - return false; - } - - // Handle select and drag - var handle = change.add(pv.Panel) - .data(dims.map(function(dim) { return {y:botRuleOffs, dy:ruleHeight, dim:dim}; })) - .left(function(t) { return x(t.dim) - 30; }) - .width(60) - .fillStyle("rgba(0,0,0,.001)") - .cursor("crosshair") - .event("mousedown", pv.Behavior.select()) - .event("select", update) - .event("selectend", selectAll) - .add(pv.Bar) - .left(25) - .top(function(d) {return d.y;}) - .width(10) - .height(function(d) { return d.dy;}) - .fillStyle(function(t) { - return (t.dim == active) ? - colors[t.dim]((filter[t.dim].max + filter[t.dim].min) / 2) : - "hsla(0,0,50%,.5)"; - }) - .strokeStyle("white") - .cursor("move") - .event("mousedown", pv.Behavior.drag()) - .event("dragstart", update) - .event("drag", update) - ; - - handle.anchor("bottom").add(pv.Label) - .textBaseline("top") - .text(function(d) { - return (dimDescr[d.dim].categorical) ? - "" : - filter[d.dim].min.toFixed(numDigits) + dimDescr[d.dim].unit - ; - }) - ; - - handle.anchor("top").add(pv.Label) - .textBaseline("bottom") - .text(function(d) { - return (dimDescr[d.dim].categorical) ? - "" : - filter[d.dim].max.toFixed(numDigits) + dimDescr[d.dim].unit; - }) - ; - - - /***** - * add the extension points - *******/ - - // Extend ParallelCoordinates - this.extend(this.pvParCoord,"parCoord"); - // the parCoord panel is the base-panel (not the colored dynamic overlay) - - // Extend body - this.extend(this.pvPanel,"chart"); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcPieChart.js b/pacotes/ccc2/pvc/pvcPieChart.js deleted file mode 100755 index 2d1db47..0000000 --- a/pacotes/ccc2/pvc/pvcPieChart.js +++ /dev/null @@ -1,63 +0,0 @@ - -/** - * PieChart is the main class for generating... pie charts (surprise!). - */ -def -.type('pvc.PieChart', pvc.BaseChart) -.add({ - _animatable: true, - - pieChartPanel: null, - - _getColorRoleSpec: function(){ - return { isRequired: true, defaultSourceRole: 'category', defaultDimension: 'color*', requireIsDiscrete: true }; - }, - - /** - * Initializes each chart's specific roles. - * @override - */ - _initVisualRoles: function(){ - - this.base(); - - this._addVisualRole('category', { - isRequired: true, - defaultDimension: 'category*', - autoCreateDimension: true - }); - - this._addVisualRole('value', { - isMeasure: true, - isRequired: true, - isPercent: true, - requireSingleDimension: true, - requireIsDiscrete: false, - valueType: Number, - defaultDimension: 'value' - }); - }, - - _initPlotsCore: function(/*hasMultiRole*/){ - new pvc.visual.PiePlot(this); - }, - - _preRenderContent: function(contentOptions) { - - this.base(); - - var isV1Compat = this.compatVersion() <= 1; - if(isV1Compat){ - var innerGap = pvc.castNumber(this.options.innerGap) || 0.95; - innerGap = def.between(innerGap, 0.1, 1); - contentOptions.paddings = ((1 - innerGap) * 100 / 2).toFixed(2) + "%"; - } else if(contentOptions.paddings == null) { - contentOptions.paddings = new pvc.PercentValue(0.025); - } - - var piePlot = this.plots.pie; - this.pieChartPanel = new pvc.PieChartPanel(this, this.basePanel, piePlot, def.create(contentOptions, { - scenes: def.getPath(this.options, 'pie.scenes') - })); - } -}); diff --git a/pacotes/ccc2/pvc/pvcPiePanel.js b/pacotes/ccc2/pvc/pvcPiePanel.js deleted file mode 100755 index 0dd3b63..0000000 --- a/pacotes/ccc2/pvc/pvcPiePanel.js +++ /dev/null @@ -1,768 +0,0 @@ - -/* - * Pie chart panel. Generates a pie chart. - * - * Specific options are: - * - * valuesVisible - Show or hide slice value. Default: false - * - * explodedSliceIndex - Index of the slice which is always exploded, or null to explode every slice. Default: null. - * - * explodedOffsetRadius - The radius by which an exploded slice is offset from the center of the pie (in pixels). - * If one wants a pie with an exploded effect, specify a value in pixels here. - * If above argument is specified, explodes only one slice, else explodes all. - * Default: 0 - * - * activeOffsetRadius - Percentage of slice radius to (additionally) explode an active slice. - * Only used if the chart has option hoverable equal to true. - * - * innerGap - The percentage of (the smallest of) the panel width or height used by the pie. - * Default: 0.9 (90%) - * - * Deprecated in favor of options leafContentMargins and leafContentPaddings. - * - * Has the following protovis extension points: - * chart_ - for the main chart Panel - * slice_ - for the main pie wedge - * sliceLabel_ - for the main pie label - * sliceLinkLine_ - for the link lines, for when labelStyle = 'linked' - * - * Example Pie Category Scene extension: - * pie: { - * scenes: { - * category: { - * sliceLabelMask: "{value} ({value.percent})" - * } - * } - * } - */ -def -.type('pvc.PieChartPanel', pvc.PlotPanel) -.init(function(chart, parent, plot, options){ - - // Before base, just to bring to attention that ValuesMask depends on it - var labelStyle = plot.option('ValuesLabelStyle'); - - this.base(chart, parent, plot, options); - - this.explodedOffsetRadius = plot.option('ExplodedSliceRadius'); - this.explodedSliceIndex = plot.option('ExplodedSliceIndex' ); - this.activeOffsetRadius = plot.option('ActiveSliceRadius' ); - this.labelStyle = labelStyle; - if(labelStyle === 'linked'){ - this.linkInsetRadius = plot.option('LinkInsetRadius' ); - this.linkOutsetRadius = plot.option('LinkOutsetRadius' ); - this.linkMargin = plot.option('LinkMargin' ); - this.linkHandleWidth = plot.option('LinkHandleWidth' ); - this.linkLabelSize = plot.option('LinkLabelSize' ); - this.linkLabelSpacingMin = plot.option('LinkLabelSpacingMin'); - } -}) -.add({ - pvPie: null, - pvPieLabel: null, - - valueRoleName: 'value', - - _getV1Datum: function(scene){ - // Ensure V1 tooltip function compatibility - var datum = scene.datum; - if(datum){ - var datumEx = Object.create(datum); - datumEx.percent = scene.vars.value.percent; - datum = datumEx; - } - - return datum; - }, - - /** - * @override - */ - _calcLayout: function(layoutInfo){ - var clientSize = layoutInfo.clientSize; - var clientWidth = clientSize.width; - var clientRadius = Math.min(clientWidth, clientSize.height) / 2; - if(!clientRadius){ - return new pvc.Size(0,0); - } - - var center = pv.vector(clientSize.width / 2, clientSize.height / 2); - - function resolvePercentRadius(radius){ - return def.between(pvc.PercentValue.resolve(radius, clientRadius), 0, clientRadius); - } - - function resolvePercentWidth(width){ - return def.between(pvc.PercentValue.resolve(width, clientWidth), 0, clientWidth); - } - - // --------------------- - - var labelFont = this._getConstantExtension('label', 'font'); - if(!def.string.is(labelFont)){ - labelFont = this.valuesFont; - } - - var maxPieRadius = clientRadius; - - if(this.valuesVisible && this.labelStyle === 'linked'){ - // Reserve space for labels and links - var linkInsetRadius = resolvePercentRadius(this.linkInsetRadius ); - var linkOutsetRadius = resolvePercentRadius(this.linkOutsetRadius); - var linkMargin = resolvePercentWidth (this.linkMargin ); - var linkLabelSize = resolvePercentWidth (this.linkLabelSize ); - - var textMargin = def.number.to(this._getConstantExtension('label', 'textMargin'), 3); - var textHeight = pv.Text.fontHeight(labelFont); - - var linkHandleWidth = this.linkHandleWidth * textHeight; // em - linkMargin += linkHandleWidth; - - var linkLabelSpacingMin = this.linkLabelSpacingMin * textHeight; // em - - var freeWidthSpace = Math.max(0, clientWidth / 2 - clientRadius); - - // Radius stolen to pie by link and label - var spaceH = Math.max(0, linkOutsetRadius + linkMargin + linkLabelSize - freeWidthSpace); - var spaceV = linkOutsetRadius + textHeight; // at least one line of text (should be half line, but this way there's a small margin...) - - var linkAndLabelRadius = Math.max(0, spaceV, spaceH); - - // Use the extra width on the label - //linkLabelSize += freeWidthSpace / 2; - - if(linkAndLabelRadius >= maxPieRadius){ - this.valuesVisible = false; - if(pvc.debug >= 2){ - this._log("Hiding linked labels due to insufficient space."); - } - } else { - - maxPieRadius -= linkAndLabelRadius; - - layoutInfo.link = { - insetRadius: linkInsetRadius, - outsetRadius: linkOutsetRadius, - elbowRadius: maxPieRadius + linkOutsetRadius, - linkMargin: linkMargin, - handleWidth: linkHandleWidth, - labelSize: linkLabelSize, - maxTextWidth: linkLabelSize - textMargin, - labelSpacingMin: linkLabelSpacingMin, - textMargin: textMargin, - lineHeight: textHeight - }; - } - } - - // --------------------- - - var explodedOffsetRadius = resolvePercentRadius(this.explodedOffsetRadius); - - var activeOffsetRadius = 0; - if(this.chart.options.hoverable){ - activeOffsetRadius = resolvePercentRadius(this.activeOffsetRadius); - } - - var effectOffsetRadius = explodedOffsetRadius + activeOffsetRadius; - - var normalPieRadius = maxPieRadius - effectOffsetRadius; - if(normalPieRadius < 0){ - return new pvc.Size(0,0); - } - - // --------------------- - - layoutInfo.center = center; - layoutInfo.clientRadius = clientRadius; - layoutInfo.normalRadius = normalPieRadius; - layoutInfo.explodedOffsetRadius = explodedOffsetRadius; - layoutInfo.activeOffsetRadius = activeOffsetRadius; - layoutInfo.labelFont = labelFont; - }, - - /** - * @override - */ - _createCore: function(layoutInfo) { - var myself = this; - var chart = this.chart; - var options = chart.options; - var visibleKeyArgs = {visible: true}; - - var rootScene = this._buildScene(); - var center = layoutInfo.center; - var normalRadius = layoutInfo.normalRadius; - - // ------------ - - var wrapper; - var extensionIds = ['slice']; - if(this.compatVersion() <= 1){ - extensionIds.push(''); // let access as "pie_" - wrapper = function(v1f){ - return function(pieCatScene){ - return v1f.call(this, pieCatScene.vars.value.value); - }; - }; - } - - this.pvPie = new pvc.visual.PieSlice(this, this.pvPanel, { - extensionId: extensionIds, - center: center, - activeOffsetRadius: layoutInfo.activeOffsetRadius, - wrapper: wrapper, - tooltipArgs: { - options: { - useCorners: true, - gravity: function(){ - var isRightPlane = Math.cos(this.midAngle()) >= 0; - var isTopPlane = Math.sin(this.midAngle()) >= 0; - return isRightPlane ? - (isTopPlane ? 'nw' : 'sw') : - (isTopPlane ? 'ne' : 'se') - ; - } - } - } - }) - - .lock('data', rootScene.childNodes) - - .override('angle', function(){ return this.scene.vars.value.angle; }) - - .override('baseOffsetRadius', function(){ - var explodeIndex = myself.explodedSliceIndex; - if (explodeIndex == null || explodeIndex == this.pvMark.index) { - return layoutInfo.explodedOffsetRadius; - } - - return this.base(); - }) - - .lock('outerRadius', function(){ return chart.animate(0, normalRadius); }) - - .localProperty('innerRadiusEx', pvc.PercentValue.parse) - - // In case the inner radius is specified, we better animate it as well - .intercept('innerRadius', function(scene){ - var innerRadius = this.delegateExtension(); - if(innerRadius == null){ - var innerRadiusPct = this.pvMark.innerRadiusEx(); - if(innerRadiusPct != null){ - innerRadius = pvc.PercentValue.resolve( - innerRadiusPct, - this.pvMark.outerRadius()) || 0; - } else { - innerRadius = 0; - } - } - - return innerRadius > 0 ? chart.animate(0, innerRadius) : 0; - }) - .pvMark - ; - - if(this.valuesVisible){ - if(this.labelStyle === 'inside'){ - - this.pvPieLabel = new pvc.visual.Label(this, this.pvPie.anchor(this.valuesAnchor), { - extensionId: 'label', - wrapper: wrapper - }) - .intercept('visible', function(scene){ - var angle = scene.vars.value.angle; - if(angle < 0.001){ - return false; - } - - return this.delegateExtension(true); - }) - .pvMark - .text(function(scene){ return scene.vars.value.sliceLabel; }) - .textMargin(10); - - } else if(this.labelStyle === 'linked') { - var linkLayout = layoutInfo.link; - - rootScene.layoutLinkLabels(layoutInfo); - - this.pvLinkPanel = this.pvPanel.add(pv.Panel) - .data(rootScene.childNodes) - .localProperty('pieSlice') - .pieSlice(function(scene){ - return myself.pvPie.scene[this.index]; - }) - ; - - this.pvLinkLine = new pvc.visual.Line( - this, - this.pvLinkPanel, - { - extensionId: 'linkLine', - freePosition: true, - noClick: true, - noDoubleClick: true, - noSelect: true, - noTooltip: true, - noHover: true - }) - .lockMark('data', function(scene){ - // Calculate the dynamic dot at the - // slice's middle angle and outer radius... - var pieSlice = this.parent.pieSlice(); - var midAngle = pieSlice.startAngle + pieSlice.angle / 2; - var outerRadius = pieSlice.outerRadius - linkLayout.insetRadius; - var x = pieSlice.left + outerRadius * Math.cos(midAngle); - var y = pieSlice.top + outerRadius * Math.sin(midAngle); - - var firstDotScene = scene.childNodes[0]; - if(!firstDotScene || !firstDotScene._isFirstDynamicScene){ - firstDotScene = new pvc.visual.PieLinkLineScene( - scene, x, y, /* index */ 0); - - firstDotScene._isFirstDynamicScene = true; - } else { - firstDotScene.x = x; - firstDotScene.y = y; - } - - return scene.childNodes; - }) - .override('defaultColor', function(type){ - if(type === 'stroke'){ - return 'black'; - } - return this.base(type); - }) - .override('defaultStrokeWidth', def.fun.constant(0.5)) - .pvMark - .lock('visible') - .lock('top', function(dot){ return dot.y; }) - .lock('left', function(dot){ return dot.x; }) - ; - - this.pvPieLabel = new pvc.visual.Label( - this, - this.pvLinkPanel, - { - extensionId: 'label', - noClick: false, - noDoubleClick: false, - noSelect: false, - noHover: false - }) - .lockMark('data', function(scene){ - // Repeat the scene, once for each line - return scene.lineScenes; - }) - .pvMark - .lock('visible') - .left (function(scene){ return scene.vars.link.labelX; }) - .top (function(scene){ return scene.vars.link.labelY + ((this.index + 1) * linkLayout.lineHeight); }) // must be mark.index because of repeating scene... - .textAlign(function(scene){ return scene.vars.link.labelAnchor; }) - .textMargin(linkLayout.textMargin) - .textBaseline('bottom') - .text (function(scene){ return scene.vars.link.labelLines[this.index]; }) - .fillStyle('red') - ; - - // - if(pvc.debug >= 20){ - this.pvPanel.add(pv.Panel) - .zOrder(-10) - .left (center.x - layoutInfo.clientRadius) - .top (center.y - layoutInfo.clientRadius) - .width (layoutInfo.clientRadius * 2) - .height(layoutInfo.clientRadius * 2) - .strokeStyle('red') - ; - - // Client Area - this.pvPanel - .strokeStyle('green'); - - var linkColors = pv.Colors.category10(); - this.pvLinkLine - .segmented(true) - .strokeStyle(function(){ return linkColors(this.index); }); - } - // - } - - this.pvPieLabel - .font(layoutInfo.labelFont); - } - }, - - _getExtensionId: function(){ - // chart is deprecated - // content coincides, visually in this chart type - // - actually it shares the same panel... - - var extensionIds = [{abs: 'content'}]; - if(this.chart.parent){ - extensionIds.push({abs: 'smallContent'}); - } - - return extensionIds.concat(this.base()); - }, - - /** - * Renders this.pvBarPanel - the parent of the marks that are affected by selection changes. - * @override - */ - renderInteractive: function(){ - this.pvPanel.render(); - }, - - /** - * Returns an array of marks whose instances are associated to a datum, or null. - * @override - */ - _getSelectableMarks: function(){ - var marks = [this.pvPie]; - if(this.pvPieLabel){ - marks.push(this.pvPieLabel); - } - - return marks; - }, - - _buildScene: function(){ - var rootScene = new pvc.visual.PieRootScene(this); - - // v1 property - this.sum = rootScene.vars.sumAbs.value; - - return rootScene; - } -}); - -def -.type('pvc.visual.PieRootScene', pvc.visual.Scene) -.init(function(panel){ - var chart = panel.chart; - var data = chart.visualRoles('category').flatten(chart.data, pvc.data.visibleKeyArgs); - var colorVarHelper = new pvc.visual.RoleVarHelper(chart, chart._colorRole); - - this.base(null, {panel: panel, group: data}); - - // --------------- - - var valueRoleName = panel.valueRoleName; - var valueDimName = chart.visualRoles(valueRoleName).firstDimensionName(); - var valueDim = data.dimensions(valueDimName); - - var options = chart.options; - var percentValueFormat = options.percentValueFormat; - - var rootScene = this; - var sumAbs = 0; - - /* Create category scene sub-class */ - var CategSceneClass = def.type(pvc.visual.PieCategoryScene) - .init(function(categData, value){ - - // Adds to parent scene... - this.base(rootScene, {group: categData}); - - this.vars.category = pvc.visual.ValueLabelVar.fromComplex(categData); - - sumAbs += Math.abs(value); - - this.vars.value = new pvc.visual.ValueLabelVar( - value, - formatValue(value, categData)); - - colorVarHelper.onNewScene(this, /* isLeaf */ true); - }); - - /* Extend with any user extensions */ - panel._extendSceneType('category', CategSceneClass, ['sliceLabel', 'sliceLabelMask']); - - /* Create child category scenes */ - data.children().each(function(categData){ - // Value may be negative - // Don't create 0-value scenes - var value = categData.dimensions(valueDimName).sum(pvc.data.visibleKeyArgs); - if(value !== 0){ - new CategSceneClass(categData, value); - } - }); - - // ----------- - - // TODO: should this be in something like: chart.axes.angle.scale ? - this.angleScale = pv.Scale - .linear(0, sumAbs) - .range(0, 2 * Math.PI) - .by1(Math.abs); - - this.vars.sumAbs = new pvc.visual.ValueLabelVar(sumAbs, formatValue(sumAbs)); - - this.childNodes.forEach(function(categScene){ - completeBuildCategScene.call(categScene); - }); - - function formatValue(value, categData){ - if(categData){ - var datums = categData._datums; - if(datums.length === 1){ - // Prefer to return the already formatted/provided label - return datums[0].atoms[valueDimName].label; - } - } - - return valueDim.format(value); - } - - /** - * @private - * @instance pvc.visual.PieCategoryScene - */ - function completeBuildCategScene(){ - var valueVar = this.vars.value; - - // Calculate angle (span) - valueVar.angle = this.parent.angleScale(valueVar.value); - - // Create percent sub-var of the value var - var percent = Math.abs(valueVar.value) / sumAbs; - - valueVar.percent = new pvc.visual.ValueLabelVar( - percent, - percentValueFormat(percent)); - - // Calculate slice label - valueVar.sliceLabel = this.sliceLabel(); - } -}) -.add({ - layoutLinkLabels: function(layoutInfo){ - var startAngle = -Math.PI / 2; - - var leftScenes = []; - var rightScenes = []; - - this.childNodes.forEach(function(categScene){ - startAngle = categScene.layoutI(layoutInfo, startAngle); - - (categScene.vars.link.dir > 0 ? rightScenes : leftScenes) - .push(categScene); - }); - - // Distribute left and right labels and finish their layout - this._distributeLabels(-1, leftScenes, layoutInfo); - this._distributeLabels(+1, rightScenes, layoutInfo); - }, - - _distributeLabels: function(dir, scenes, layoutInfo){ - // Initially, for each category scene, - // targetY = elbowY - // Taking additionally labelHeight into account, - // if this position causes overlapping, find a != targetY - // that does not cause overlap. - - // Sort scenes by Y position - scenes.sort(function(sceneA, sceneB){ - return def.compare(sceneA.vars.link.targetY, sceneB.vars.link.targetY); - }); - - /*jshint expr:true */ - this._distributeLabelsDownwards(scenes, layoutInfo) && - this._distributeLabelsUpwards (scenes, layoutInfo) && - this._distributeLabelsEvenly (scenes, layoutInfo); - - scenes.forEach(function(categScene){ - categScene.layoutII(layoutInfo); - }); - }, - - _distributeLabelsDownwards: function(scenes, layoutInfo){ - var linkLayout = layoutInfo.link; - var labelSpacingMin = linkLayout.labelSpacingMin; - var yMax = layoutInfo.clientSize.height; - var overlapping = false; - for(var i = 0, J = scenes.length - 1 ; i < J ; i++){ - var linkVar0 = scenes[i].vars.link; - - if(!i && linkVar0.labelTop() < 0){ - overlapping = true; - } - - var linkVar1 = scenes[i + 1].vars.link; - var labelTopMin1 = linkVar0.labelBottom() + labelSpacingMin; - if (linkVar1.labelTop() < labelTopMin1) { - - var halfLabelHeight1 = linkVar1.labelHeight / 2; - var targetY1 = labelTopMin1 + halfLabelHeight1; - var targetYMax = yMax - halfLabelHeight1; - if(targetY1 > targetYMax){ - overlapping = true; - linkVar1.targetY = targetYMax; - } else { - linkVar1.targetY = targetY1; - } - } - } - - return overlapping; - }, - - _distributeLabelsUpwards: function(scenes, layoutInfo){ - var linkLayout = layoutInfo.link; - var labelSpacingMin = linkLayout.labelSpacingMin; - - var overlapping = false; - for(var i = scenes.length - 1 ; i > 0 ; i--){ - var linkVar1 = scenes[i - 1].vars.link; - var linkVar0 = scenes[i].vars.link; - if(i === 1 && linkVar1.labelTop() < 0){ - overlapping = true; - } - - var labelBottomMax1 = linkVar0.labelTop() - labelSpacingMin; - if (linkVar1.labelBottom() > labelBottomMax1) { - var halfLabelHeight1 = linkVar1.labelHeight / 2; - var targetY1 = labelBottomMax1 - halfLabelHeight1; - var targetYMin = halfLabelHeight1; - if(targetY1 < targetYMin){ - overlapping = true; - linkVar1.targetY = targetYMin; - } else { - linkVar1.targetY = targetY1; - } - } - } - - return overlapping; - }, - - _distributeLabelsEvenly: function(scenes, layoutInfo){ - var linkLayout = layoutInfo.link; - var labelSpacingMin = linkLayout.labelSpacingMin; - - var totalHeight = 0; - scenes.forEach(function(categScene){ - totalHeight += categScene.vars.link.labelHeight; - }); - - var freeSpace = layoutInfo.clientSize.height - totalHeight; // may be < 0 - var labelSpacing = freeSpace; - if(scenes.length > 1){ - labelSpacing /= (scenes.length - 1); - } - - var y = 0; - scenes.forEach(function(scene){ - var linkVar = scene.vars.link; - var halfLabelHeight = linkVar.labelHeight / 2; - y += halfLabelHeight; - linkVar.targetY = y; - y += halfLabelHeight + labelSpacing; - }); - - return true; - } -}); - -def -.type('pvc.visual.PieLinkLabelVar') // TODO : Var base class -.add({ - labelTop: function(){ - return this.targetY - this.labelHeight / 2; - }, - - labelBottom: function(){ - return this.targetY + this.labelHeight / 2; - } -}); - -def -.type('pvc.visual.PieCategoryScene', pvc.visual.Scene) -.add({ - // extendable - sliceLabelMask: function(){ - return this.panel().valuesMask; - }, - - // extendable - sliceLabel: function(){ - return this.format(this.sliceLabelMask()); - }, - - layoutI: function(layoutInfo, startAngle){ - var valueVar = this.vars.value; - var endAngle = startAngle + valueVar.angle; - var midAngle = (startAngle + endAngle) / 2; - - // Overwrite existing link var, if any. - var linkVar = (this.vars.link = new pvc.visual.PieLinkLabelVar()); - - var linkLayout = layoutInfo.link; - - var labelLines = pvc.text.justify(valueVar.sliceLabel, linkLayout.maxTextWidth, layoutInfo.labelFont); - var lineCount = labelLines.length; - linkVar.labelLines = labelLines; - linkVar.labelHeight = lineCount * linkLayout.lineHeight; - - this.lineScenes = def.array.create(lineCount, this); - - var cosMid = Math.cos(midAngle); - var sinMid = Math.sin(midAngle); - - var isAtRight = cosMid >= 0; - var dir = isAtRight ? 1 : -1; - - // Label anchor is at the side with opposite name to the side of the pie where it is placed. - linkVar.labelAnchor = isAtRight ? 'left' : 'right'; - - var center = layoutInfo.center; - var elbowRadius = linkLayout.elbowRadius; - var elbowX = center.x + elbowRadius * cosMid; - var elbowY = center.y + elbowRadius * sinMid; // baseY - - var anchorX = center.x + dir * elbowRadius; - var targetX = anchorX + dir * linkLayout.linkMargin; - - new pvc.visual.PieLinkLineScene(this, elbowX, elbowY); - new pvc.visual.PieLinkLineScene(this, anchorX, elbowY); - - linkVar.elbowY = elbowY; - linkVar.targetY = elbowY + 0; - linkVar.targetX = targetX; - linkVar.dir = dir; - - return endAngle; - }, - - layoutII: function(layoutInfo){ - var linkVar = this.vars.link; - - var targetY = linkVar.targetY; - var targetX = linkVar.targetX; - - var handleWidth = layoutInfo.link.handleWidth; - if(handleWidth > 0){ - new pvc.visual.PieLinkLineScene(this, targetX - linkVar.dir * handleWidth, targetY); - } - - new pvc.visual.PieLinkLineScene(this, targetX, targetY); - - linkVar.labelX = targetX; - linkVar.labelY = targetY - linkVar.labelHeight/2; - } -}); - -def -.type('pvc.visual.PieLinkLineScene', pvc.visual.Scene) -.init(function(catScene, x, y, index){ - this.base(catScene, { group: catScene.group, index: index }); - - this.x = x; - this.y = y; -}) -.add(pv.Vector) -; \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcPlotBgPanel.js b/pacotes/ccc2/pvc/pvcPlotBgPanel.js deleted file mode 100755 index 606503e..0000000 --- a/pacotes/ccc2/pvc/pvcPlotBgPanel.js +++ /dev/null @@ -1,30 +0,0 @@ - -def -.type('pvc.PlotBgPanel', pvc.BasePanel) -.init(function(chart, parent, options) { - // Prevent the border from affecting the box model, - // providing a static 0 value, independently of the actual drawn value... - //this.borderWidth = 0; - - this.base(chart, parent, options); - - //this._extensionPrefix = "plotBg"; -}) -.add({ - anchor: 'fill', - - _getExtensionId: function(){ - return 'plotBg'; - }, - - _createCore: function(layoutInfo) { - // Send the panel behind grid rules - this.pvPanel - .borderPanel - .lock('zOrder', -13) - .antialias(false) - ; - - this.base(layoutInfo); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcPlotPanel.js b/pacotes/ccc2/pvc/pvcPlotPanel.js deleted file mode 100755 index 4251799..0000000 --- a/pacotes/ccc2/pvc/pvcPlotPanel.js +++ /dev/null @@ -1,52 +0,0 @@ - -def -.type('pvc.PlotPanel', pvc.BasePanel) -.init(function(chart, parent, plot, options) { - // Prevent the border from affecting the box model, - // providing a static 0 value, independently of the actual drawn value... - //this.borderWidth = 0; - - this.base(chart, parent, options); - - this.plot = plot; - this._extensionPrefix = plot.extensionPrefixes; - this.dataPartValue = plot.option('DataPart'); - this.axes.color = chart._getAxis('color', (plot.option('ColorAxis') || 0) - 1); - this.orientation = plot.option('Orientation' ); - this.valuesVisible = plot.option('ValuesVisible'); - this.valuesAnchor = plot.option('ValuesAnchor' ); - this.valuesMask = plot.option('ValuesMask' ); - this.valuesFont = plot.option('ValuesFont' ); - - var roles = this.visualRoles = Object.create(chart._visualRoles); - - var colorRoleName = plot.option('ColorRole'); - roles.color = colorRoleName ? chart.visualRoles(colorRoleName) : null; - - this.chart._addPlotPanel(this); -}) -.add({ - anchor: 'fill', - - visualRoles: null, - - _getExtensionId: function(){ - // chart is deprecated - var extensionIds = ['chart', 'plot']; - if(this.plotName){ - extensionIds.push(this.plotName); - } - - return extensionIds; - }, - - /* @override */ - isOrientationVertical: function(){ - return this.orientation === pvc.orientation.vertical; - }, - - /* @override */ - isOrientationHorizontal: function(){ - return this.orientation === pvc.orientation.horizontal; - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcPoint.js b/pacotes/ccc2/pvc/pvcPoint.js deleted file mode 100755 index 6ffadeb..0000000 --- a/pacotes/ccc2/pvc/pvcPoint.js +++ /dev/null @@ -1,232 +0,0 @@ - -/** - * PointAbstract is the class that will be extended by - * dot, line, stacked-line and area charts. - */ -def -.type('pvc.PointAbstract', pvc.CategoricalAbstract) -.add({ - _animatable: true, - - _processOptionsCore: function(options){ - // Has no meaning in this chart type - options.panelSizeRatio = 1; - - this.base(options); - }, - - _hasDataPartRole: function(){ - return true; - }, - - /** - * Initializes each chart's specific roles. - * @override - */ - _initVisualRoles: function(){ - - this.base(); - - this._addVisualRole('value', { - isMeasure: true, - isRequired: true, - isPercent: this.options.stacked, - requireSingleDimension: true, - requireIsDiscrete: false, - valueType: Number, - defaultDimension: 'value' - }); - }, - - _initPlotsCore: function(/*hasMultiRole*/){ - var options = this.options; - - var pointPlot = this._createPointPlot(); - var trend = pointPlot.option('Trend'); - - if(options.plot2){ - // Line Plot - var plot2Plot = new pvc.visual.PointPlot(this, { - name: 'plot2', - fixed: { - DataPart: '1' - }, - defaults: { - ColorAxis: 2, - LinesVisible: true, - DotsVisible: true - }}); - - if(!trend){ - trend = plot2Plot.option('Trend'); - } - } - - if(trend){ - // Trend Plot - new pvc.visual.PointPlot(this, { - name: 'trend', - fixed: { - DataPart: 'trend', - TrendType: 'none', - ColorRole: 'series', // one trend per series - NullInterpolatioMode: 'none' - }, - defaults: { - ColorAxis: 2, - LinesVisible: true, - DotsVisible: false - } - }); - } - }, - - _bindAxes: function(hasMultiRole){ - - this.base(hasMultiRole); - - // Set defaults of Offset property - var typeAxes = this.axesByType.base; - if(typeAxes){ - typeAxes.forEach(function(axis){ - var isDiscrete = axis.scaleType === 'discrete'; - if(!isDiscrete){ - axis.option.defaults({Offset: 0.01}); - } - }); - } - - typeAxes = this.axesByType.ortho; - if(typeAxes){ - typeAxes.forEach(function(axis){ - axis.option.defaults({Offset: 0.04}); - }); - } - }, - - //_createPointPlot: function(){}, - - /* @override */ - _createPlotPanels: function(parentPanel, baseOptions){ - var plots = this.plots; - - var pointPlot = plots.point; - this.scatterChartPanel = - new pvc.PointPanel( - this, - parentPanel, - pointPlot, - Object.create(baseOptions)); - - var plot2Plot = plots.plot2; - if(plot2Plot){ - if(pvc.debug >= 3){ - this._log("Creating second Point panel."); - } - - new pvc.PointPanel( - this, - parentPanel, - plot2Plot, - Object.create(baseOptions)); - } - - var trendPlot = plots.trend; - if(trendPlot){ - if(pvc.debug >= 3){ - this._log("Creating Trends Point panel."); - } - - new pvc.PointPanel( - this, - parentPanel, - trendPlot, - Object.create(baseOptions)); - } - }, - - defaults: { - tooltipOffset: 10 - } -}); - -/** - * Dot Chart - */ -def -.type('pvc.DotChart', pvc.PointAbstract) -.add({ - _createPointPlot: function(){ - return new pvc.visual.PointPlot(this, { - fixed: {DotsVisible: true} - }); - } -}); - -/** - * Line Chart - */ -def -.type('pvc.LineChart', pvc.PointAbstract) -.add({ - _createPointPlot: function(){ - return new pvc.visual.PointPlot(this, { - fixed: {LinesVisible: true} - }); - } -}); - -/** - * Area Chart - */ -def -.type('pvc.AreaChart', pvc.PointAbstract) -.add({ - _createPointPlot: function(){ - return new pvc.visual.PointPlot(this, { - fixed: {AreasVisible: true} - }); - } -}); - -/** - * Stacked Line Chart - */ -pvc.mStackedLineChart = // V1 compatibility -def -.type('pvc.StackedLineChart', pvc.PointAbstract) -.add({ - _createPointPlot: function(){ - return new pvc.visual.PointPlot(this, { - fixed: {LinesVisible: true, Stacked: true} - }); - } -}); - -/** - * Stacked Dot Chart - */ -def -.type('pvc.StackedDotChart', pvc.PointAbstract) -.add({ - _createPointPlot: function(){ - return new pvc.visual.PointPlot(this, { - fixed: {DotsVisible: true, Stacked: true} - }); - } -}); - -/** - * Stacked Area Chart - */ -pvc.mStackedAreaChart = // V1 compatibility -def -.type('pvc.StackedAreaChart', pvc.PointAbstract) -.add({ - _createPointPlot: function(){ - return new pvc.visual.PointPlot(this, { - fixed: {AreasVisible: true, Stacked: true}, - defaults: {LinesVisible: true} - }); - } -}); diff --git a/pacotes/ccc2/pvc/pvcPointPanel.js b/pacotes/ccc2/pvc/pvcPointPanel.js deleted file mode 100755 index 5137f3c..0000000 --- a/pacotes/ccc2/pvc/pvcPointPanel.js +++ /dev/null @@ -1,853 +0,0 @@ -/* - * Point panel. - * Class that draws all line/dot/area combinations. - * Specific options are: - * dotsVisible - Show or hide dots. Default: true - * areasVisible - Show or hide dots. Default: false - * linesVisible - Show or hide dots. Default: true - * valuesVisible - Show or hide line value. Default: false - * - * Has the following protovis extension points: - * - * chart_ - for the main chart Panel - * line_ - for the actual line - * linePanel_ - for the panel where the lines sit - * lineDot_ - the dots on the line - * lineLabel_ - for the main line label - */ -def -.type('pvc.PointPanel', pvc.CategoricalAbstractPanel) -.init(function(chart, parent, plot, options) { - - this.base(chart, parent, plot, options); - - this.linesVisible = plot.option('LinesVisible'); // TODO - this.dotsVisible = plot.option('DotsVisible' ); // TODO - this.areasVisible = plot.option('AreasVisible'); // TODO - if(!this.linesVisible && !this.dotsVisible && !this.areasVisible){ - this.linesVisible = true; - plot.option.specify({'LinesVisible': true}); - } -}) -.add({ - pvLine: null, - pvArea: null, - pvDot: null, - pvLabel: null, - pvScatterPanel: null, - - _creating: function(){ - // Register BULLET legend prototype marks - var groupScene = this.defaultVisibleBulletGroupScene(); - if(groupScene && !groupScene.hasRenderer()){ - var colorAxis = groupScene.colorAxis; - var drawMarker = def.nullyTo(colorAxis.option('LegendDrawMarker', /*no default*/ true), this.dotsVisible || this.areasVisible); - var drawRule = !drawMarker || - def.nullyTo(colorAxis.option('LegendDrawLine', /*no default*/ true), this.linesVisible && !this.areasVisible); - if(drawMarker || drawRule){ - var keyArgs = {}; - if((keyArgs.drawMarker = drawMarker)){ - var markerShape = colorAxis.option('LegendShape', true); - - if(this.dotsVisible){ - if(!markerShape){ - markerShape = 'circle'; // Dot's default shape - } - - keyArgs.markerPvProto = new pv.Dot() - .lineWidth(1.5, pvc.extensionTag) // act as if it were a user extension - .shapeSize(12, pvc.extensionTag); // idem - } else { - keyArgs.markerPvProto = new pv.Mark(); - } - - keyArgs.markerShape = markerShape; - - if(this._applyV1BarSecondExtensions){ - this.chart.extend(keyArgs.markerPvProto, 'barSecondDot', {constOnly: true}); - } - this.extend(keyArgs.markerPvProto, 'dot', {constOnly: true}); - } - - if((keyArgs.drawRule = drawRule)){ - keyArgs.rulePvProto = new pv.Line() - .lineWidth(1.5, pvc.extensionTag); - - if(this._applyV1BarSecondExtensions){ - this.chart.extend(keyArgs.rulePvProto, 'barSecondLine', {constOnly: true}); - } - this.extend(keyArgs.rulePvProto, 'line', {constOnly: true}); - } - - groupScene.renderer( - new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs)); - } - } - }, - - /** - * @override - */ - _createCore: function(){ - this.base(); - - var myself = this; - var chart = this.chart; - var isStacked = this.stacked; - var dotsVisible = this.dotsVisible; - var areasVisible = this.areasVisible; - var linesVisible = this.linesVisible; - var anchor = this.isOrientationVertical() ? "bottom" : "left"; - - this.valueRole = chart.visualRoles(this.plot.option('OrthoRole')); - this.valueRoleName = this.valueRole.name; - this.valueDimName = this.valueRole.firstDimensionName(); - - // ------------------ - // DATA - var isBaseDiscrete = this.axes.base.role.grouping.isDiscrete(); - var data = this.visibleData(); // shared "categ then series" grouped data - var rootScene = this._buildScene(data, isBaseDiscrete); - - // --------------- - // BUILD - if(areasVisible){ - // Areas don't look good above the axes - this.pvPanel.zOrder(-7); - } else { - // // Above axes - this.pvPanel.zOrder(1); - } - - this.pvScatterPanel = new pvc.visual.Panel(this, this.pvPanel, { - extensionId: 'panel' - }) - .lock('data', rootScene.childNodes) - .pvMark - ; - - // -- AREA -- - var areaFillColorAlpha = areasVisible && linesVisible && !isStacked ? 0.5 : null; - - var wrapper; - if(this.compatVersion() <= 1){ - if(isStacked){ - wrapper = function(v1f){ - return function(dotScene){ - return v1f.call(this, dotScene.vars.value.rawValue); - }; - }; - } else { - wrapper = function(v1f){ - return function(dotScene){ - var d = { - category: dotScene.vars.category.rawValue, - value: dotScene.vars.value.rawValue - }; - - // Compensate for the effect of intermediate scenes on mark's index - var pseudo = Object.create(this); - pseudo.index = dotScene.dataIndex; - return v1f.call(pseudo, d); - }; - }; - } - } - - var isLineAreaVisible = isBaseDiscrete && isStacked ? - function(){ return !this.scene.isNull || this.scene.isIntermediate; } : - function(){ return !this.scene.isNull; }; - - var isLineAreaNoSelect = /*dotsVisible && */chart._canSelectWithFocusWindow(); - - this.pvArea = new pvc.visual.Area(this, this.pvScatterPanel, { - extensionId: 'area', - noTooltip: false, - wrapper: wrapper, - noSelect: isLineAreaNoSelect, - showsSelection: !isLineAreaNoSelect - }) - .lock('visible', isLineAreaVisible) - // If it were allowed to hide the line this way, the anchored dot would fail to evaluate -// .intercept('visible', function(){ -// return isLineAreaVisible && this.delegateExtension(true); -// }) - /* Data */ - .lock('data', function(seriesScene){ return seriesScene.childNodes; }) // TODO - - /* Position & size */ - .override('x', function(){ return this.scene.basePosition; }) // left - .override('y', function(){ return this.scene.orthoPosition; }) // bottom - .override('dy', function(){ return chart.animate(0, this.scene.orthoLength); }) // height - - /* Color & Line */ - .override('color', function(type){ - return areasVisible ? this.base(type) : null; - }) - .override('baseColor', function(type){ - var color = this.base(type); - if(!this._finished && color && areaFillColorAlpha != null){ - color = color.alpha(areaFillColorAlpha); - } - - return color; - }) - .override('dimColor', function(color, type){ - return isStacked ? - pvc.toGrayScale(color, 1, null, null).brighter() : - this.base(color, type); - }) - .lock('events', areasVisible ? 'painted' : 'none') - .pvMark - ; - - // -- LINE -- - var dotsVisibleOnly = dotsVisible && !linesVisible && !areasVisible, - - /* When not showing lines, but showing areas, - * we copy the area fillStyle so that - * the line can cover the area and not be noticed. - * We need this to hide the ladder - * on the border of the area, - * due to not using antialias. - * - * When the scene has the active series, - * the line is shown "highlighted" anyway. - */ - lineCopiesAreaColor = !linesVisible && areasVisible, - - /* When areas are shown with no alpha (stacked), - * make dots darker so they get - * distinguished from areas. - */ - darkerLineAndDotColor = isStacked && areasVisible; - - var extensionIds = ['line']; - if(this._applyV1BarSecondExtensions){ - extensionIds.push({abs: 'barSecondLine'}); - } - - /* - * Line.visible = - * a) linesVisible - * or - * b) (!linesVisible and) areasVisible - * and - * b.1) discrete base and stacked - * and - * b.1.1) not null or is an intermediate null - * b.2) not null - */ - var isLineVisible = !dotsVisibleOnly && isLineAreaVisible; - - this.pvLine = new pvc.visual.Line( - this, - this.pvArea.anchor(this.anchorOpposite(anchor)), - { - extensionId: extensionIds, - freePosition: true, - wrapper: wrapper, - noTooltip: false, - noSelect: isLineAreaNoSelect, - showsSelection: !isLineAreaNoSelect - }) - .lock('visible', isLineVisible) - // If it were allowed to hide the line this way, the anchored dot would fail to evaluate -// .intercept('visible', function(){ -// return isLineVisible && this.delegateExtension(true); -// }) - /* Color & Line */ - .override('defaultColor', function(type){ - var color = this.base(type); - - if(!this._finished && darkerLineAndDotColor && color){ - color = color.darker(0.6); - } - return color; - }) - .override('normalColor', function(color, type){ - return linesVisible ? color : null; - }) - .override('baseStrokeWidth', function(){ - var strokeWidth; - if(linesVisible){ - strokeWidth = this.base(); - } - - return strokeWidth == null ? 1.5 : strokeWidth; - }) - .intercept('strokeDasharray', function(){ - var dashArray = this.delegateExtension(); - if(dashArray === undefined){ - var scene = this.scene; - var useDash = scene.isInterpolated; - if(!useDash){ - var next = scene.nextSibling; - useDash = next && next.isIntermediate && next.isInterpolated; - if(!useDash){ - var previous = scene.previousSibling; - useDash = previous && scene.isIntermediate && previous.isInterpolated; - } - } - - dashArray = useDash ? '. ' : null; - } - - return dashArray; - }) - .pvMark - ; - - - // -- DOT -- - var showAloneDots = !(areasVisible && isBaseDiscrete && isStacked); - - extensionIds = ['dot']; - if(this._applyV1BarSecondExtensions){ - extensionIds.push({abs: 'barSecondDot'}); - } - - this.pvDot = new pvc.visual.Dot(this, this.pvLine, { - extensionId: extensionIds, - freePosition: true, - wrapper: wrapper - }) - .intercept('visible', function(){ - var scene = this.scene; - return (!scene.isNull && !scene.isIntermediate /*&& !scene.isInterpolated*/) && - this.delegateExtension(true); - }) - .override('color', function(type){ - /* - * Handle dotsVisible - * ----------------- - * Despite !dotsVisible, - * show a dot anyway when: - * 1) it is active, or - * 2) it is single (the only dot in its series and there's only one category) (and in areas+discreteCateg+stacked case) - * 3) it is alone (surrounded by null dots) (and not in areas+discreteCateg+stacked case) - */ - if(!dotsVisible){ - var visible = this.scene.isActive || - (!showAloneDots && this.scene.isSingle) || - (showAloneDots && this.scene.isAlone); - if(!visible) { - return pvc.invisibleFill; - } - } - - // TODO: review interpolated style/visibility - if(this.scene.isInterpolated && type === 'fill'){ - var color = this.base(type); - return color && pv.color(color).brighter(0.5); - } - - // Follow normal logic - return this.base(type); - }) -// .override('interactiveColor', function(color, type){ -// return this.scene.isInterpolated && type === 'stroke' ? -// color : -// this.base(color, type); -// }) - .optionalMark('lineCap', 'round') -// .intercept('strokeDasharray', function(){ -// var dashArray = this.delegateExtension(); -// if(dashArray === undefined){ -// // TODO: review interpolated style/visibility -// dashArray = this.scene.isInterpolated ? '.' : null; -// } -// -// return dashArray; -// }) - .override('defaultColor', function(type){ - var color = this.base(type); - - if(!this._finished && darkerLineAndDotColor && color){ - color = color.darker(0.6); - } - return color; - }) - .override('baseSize', function(){ - /* When not showing dots, - * but a datum is alone and - * wouldn't be visible using lines or areas, - * show the dot anyway, - * with a size = to the line's width^2 - * (ideally, a line would show as a dot when only one point?) - */ - if(!dotsVisible) { - var visible = this.scene.isActive || - (!showAloneDots && this.scene.isSingle) || - (showAloneDots && this.scene.isAlone); - - if(visible && !this.scene.isActive) { - // Obtain the line Width of the "sibling" line - var lineWidth = Math.max(myself.pvLine.lineWidth(), 0.2) / 2; - return lineWidth * lineWidth; - } - } - - // TODO: review interpolated style/visibility - if(this.scene.isInterpolated){ - return 0.8 * this.base(); - } - - return this.base(); - }) - .pvMark - ; - - // -- LABEL -- - if(this.valuesVisible){ - this.pvLabel = new pvc.visual.Label( - this, - this.pvDot.anchor(this.valuesAnchor), - { - extensionId: 'label', - wrapper: wrapper - }) - .pvMark - .font(this.valuesFont) // default - .text(function(scene){ return scene.vars.value.label; }) - ; - } - }, - - /** - * Renders this.pvScatterPanel - the parent of the marks that are affected by interaction changes. - * @override - */ - renderInteractive: function(){ - this.pvScatterPanel.render(); - }, - - /** - * Returns an array of marks whose instances are associated to a datum or group, or null. - * @override - */ - _getSelectableMarks: function(){ - var marks = []; - - marks.push(this.pvDot); - - if(this.linesVisible || this.areasVisible){ - marks.push(this.pvLine); - } - - return marks; - }, - - /* On each series, scenes for existing categories are interleaved with intermediate scenes. - * - * Protovis Dots are only shown for main (non-intermediate) scenes. - * - * The desired effect is that selecting a dot selects half of the - * line on the left and half of the line on the right. - * - * * main scene - * + intermediate scene - * - line that starts from the previous scene - * - * - * * - + - * - + - * - * [-------[ - * ^ line extent of a dot - * - * Each segment of a Protovis segmented line starts from the initial point - * till just before the next point. - * - * So, selecting a dot must select the the line that starts on the - * main dot, but also the line that starts on the previous intermediate dot. - * - * If a main dot shares its datums (or group) with its preceding - * intermediate dot, the selection will work like so. - * - * ------- - * - * Another influencing concern is interpolation. - * - * The desired effect is that any two dots separated by a number of missing/null - * categories get connected by linearly interpolating the missing values. - * Moreover, the left half of the new line should be selected - * when the left dot is selected and the right half of the new line - * should be selected when the right dot is selected . - * - * In the discrete-base case, the "half of the line" point always coincides - * a) with the point of an existing category (when count of null categs is odd) - * or - * b) with an intermediate point added afterwards (when count of null categs is even). - * - * a) Interpolate missing/null category in S1 (odd case) - * mid point ----v - * S1 * - + - 0 - + - * - + - * - * S2 * - + - * - + - * - + - * - * Data A A B B B B C - * - * a) Interpolate missing/null category in S1 (even case) - * mid point ------v - * S1 * - + - 0 - + - 0 - + - * - + - * - * S2 * - + - * - + - * - + - * - + - * - * Data A A A B B B B - * - * In the continuous-base case, - * the middle point between two non-null categories - * separated by missing/null categories in between, - * does not, in general, coincide with the position of an existing category... - * - * As such, interpolation may add new "main" points (to all the series), - * and interpolation of one series leads to the interpolation - * on a series that did not initially need interpolation... - * - * Interpolated dots to the left of the mid point are bound to - * the left data and interpolated dots to the right and - * including the mid point are bound to the right data. - */ - - _buildScene: function(data, isBaseDiscrete){ - var rootScene = new pvc.visual.Scene(null, {panel: this, group: data}); - var categDatas = data._children; - var chart = this.chart; - var colorVarHelper = new pvc.visual.RoleVarHelper(chart, chart._colorRole); - var valueDim = data.owner.dimensions(this.valueDimName); - var isStacked = this.stacked; - var visibleKeyArgs = {visible: true, zeroIfNone: false}; - var orthoScale = this.axes.ortho.scale; - var orthoNullValue = def.scope(function(){ - // If the data does not cross the origin, - // Choose the value that's closer to 0. - var domain = orthoScale.domain(), - dmin = domain[0], - dmax = domain[1]; - if(dmin * dmax >= 0) { - // Both positive or both negative or either is zero - return dmin >= 0 ? dmin : dmax; - } - - return 0; - }); - var orthoZero = orthoScale(orthoNullValue/*0*/); - var sceneBaseScale = this.axes.base.sceneScale({sceneVarName: 'category'}); - - // ---------------------------------- - // I - Create series scenes array. - // ---------------------------------- - def - .scope(function(){ - var serRole = chart._serRole; - return (serRole && serRole.grouping) ? - serRole.flatten(data).children() : // data already only contains visible data - def.query([null]) // null series - ; - }) - /* Create series scene */ - .each(function(seriesData1/*, seriesIndex*/){ - var seriesScene = new pvc.visual.Scene(rootScene, {group: seriesData1 || data}); - - seriesScene.vars.series = pvc.visual.ValueLabelVar.fromComplex(seriesData1); - - colorVarHelper.onNewScene(seriesScene, /* isLeaf */ false); - - /* Create series-categ scene */ - categDatas.forEach(function(categData, categIndex){ - var group = categData; - if(seriesData1){ - group = group._childrenByKey[seriesData1.key]; - } - - var value = group ? - group.dimensions(valueDim.name).sum(visibleKeyArgs) : - null; - - var serCatScene = new pvc.visual.Scene(seriesScene, {group: group}); - - // ------------- - serCatScene.dataIndex = categIndex; - - serCatScene.vars.category = pvc.visual.ValueLabelVar.fromComplex(categData); - - // ------------- - - var valueVar = new pvc.visual.ValueLabelVar( - value, - valueDim.format(value), - value); - - /* accumulated value, for stacked */ - // NOTE: the null value can only happen if interpolation is 'none' - valueVar.accValue = value != null ? value : orthoNullValue; - - serCatScene.vars.value = valueVar; - - colorVarHelper.onNewScene(serCatScene, /* isLeaf */ true); - - // ------------- - - var isInterpolated = false; - //var isInterpolatedMiddle = false; - if(group){ - var firstDatum = group._datums[0]; - if(firstDatum && firstDatum.isInterpolated){ - isInterpolated = true; - //isInterpolatedMiddle = firstDatum.isInterpolatedMiddle; - } - } - - serCatScene.isInterpolated = isInterpolated; - //serCatScene.isInterpolatedMiddle = isInterpolatedMiddle; - - // TODO: selection, owner Scene ? - //if(scene.isInterpolated){ - // scene.ownerScene = toScene; - //} - - // ------------- - - serCatScene.isNull = value == null; - serCatScene.isIntermediate = false; - }, this); - - }, this); - - // reversed so that "below == before" w.r.t. stacked offset calculation - // See {@link belowSeriesScenes2} variable. - var reversedSeriesScenes = rootScene.children().reverse().array(); - - /** - * Update the scene tree to include intermediate leaf-scenes, - * to help in the creation of lines and areas. - */ - var belowSeriesScenes2; // used below, by completeSeriesScenes - reversedSeriesScenes.forEach(completeSeriesScenes, this); - - /** - * Trim leading and trailing null scenes. - */ - reversedSeriesScenes.forEach(trimNullSeriesScenes, this); - - return rootScene; - - function completeSeriesScenes(seriesScene) { - var seriesScenes2 = [], - seriesScenes = seriesScene.childNodes, - fromScene, - notNullCount = 0, - firstAloneScene = null; - - /* As intermediate nodes are added, - * seriesScene.childNodes array is changed. - * - * The var 'toChildIndex' takes inserts into account; - * its value is always the index of 'toScene' in - * seriesScene.childNodes. - */ - for(var c = 0, /* category index */ - toChildIndex = 0, - categCount = seriesScenes.length ; - c < categCount ; - c++, - toChildIndex++) { - - var toScene = seriesScenes[toChildIndex], - c2 = c * 2; /* doubled category index, for seriesScenes2 */ - - seriesScenes2[c2] = toScene; - - /* Complete toScene */ - completeMainScene.call(this, - fromScene, - toScene, - /* belowScene */ - belowSeriesScenes2 && belowSeriesScenes2[c2]); - - if(toScene.isAlone && !firstAloneScene){ - firstAloneScene = toScene; - } - - if(!toScene.isNull){ - notNullCount++; - } - - /* Possibly create intermediate scene - * (between fromScene and toScene) - */ - if(fromScene) { - var interScene = createIntermediateScene.call(this, - seriesScene, - fromScene, - toScene, - toChildIndex, - /* belowScene */ - belowSeriesScenes2 && belowSeriesScenes2[c2 - 1]); - - if(interScene){ - seriesScenes2[c2 - 1] = interScene; - toChildIndex++; - } - } - - // -------- - - fromScene = toScene; - } - - if(notNullCount === 1 && firstAloneScene && categCount === 1){ - firstAloneScene.isSingle = true; - } - - if(isStacked){ - belowSeriesScenes2 = seriesScenes2; - } - } - - function completeMainScene( - fromScene, - toScene, - belowScene){ - - var toAccValue = toScene.vars.value.accValue; - - if(belowScene) { - if(toScene.isNull && !isBaseDiscrete) { - toAccValue = orthoNullValue; - } else { - toAccValue += belowScene.vars.value.accValue; - } - - toScene.vars.value.accValue = toAccValue; - } - - toScene.basePosition = sceneBaseScale(toScene); - toScene.orthoPosition = orthoZero; - toScene.orthoLength = orthoScale(toAccValue) - orthoZero; - - var isNullFrom = (!fromScene || fromScene.isNull), - isAlone = isNullFrom && !toScene.isNull; - if(isAlone) { - // Confirm, looking ahead - var nextScene = toScene.nextSibling; - isAlone = !nextScene || nextScene.isNull; - } - - toScene.isAlone = isAlone; - toScene.isSingle = false; - } - - function createIntermediateScene( - seriesScene, - fromScene, - toScene, - toChildIndex, - belowScene){ - - var interIsNull = fromScene.isNull || toScene.isNull; - if(interIsNull && !this.areasVisible) { - return null; - } - - var interValue, interAccValue, interBasePosition; - - if(interIsNull) { - /* Value is 0 or the below value */ - if(belowScene && isBaseDiscrete) { - var belowValueVar = belowScene.vars.value; - interAccValue = belowValueVar.accValue; - interValue = belowValueVar[this.valueRoleName]; - } else { - interValue = interAccValue = orthoNullValue; - } - - if(isStacked && isBaseDiscrete) { - // The intermediate point is at the start of the "to" band - // don't use .band, cause it does not include margins... - interBasePosition = toScene.basePosition - (sceneBaseScale.range().step / 2); - } else if(fromScene.isNull) { // Come from NULL - // Align directly below the (possibly) non-null dot - interBasePosition = toScene.basePosition; - } else /*if(toScene.isNull) */{ // Go to NULL - // Align directly below the non-null from dot - interBasePosition = fromScene.basePosition; - } -// else { -// interBasePosition = (toScene.basePosition + fromScene.basePosition) / 2; -// } - } else { - var fromValueVar = fromScene.vars.value, - toValueVar = toScene.vars.value; - - interValue = (toValueVar.value + fromValueVar.value) / 2; - - // Average of the already offset values - interAccValue = (toValueVar.accValue + fromValueVar.accValue ) / 2; - interBasePosition = (toScene.basePosition + fromScene.basePosition) / 2; - } - - //---------------- - - var interScene = new pvc.visual.Scene(seriesScene, { - /* insert immediately before toScene */ - index: toChildIndex, - group: /*toScene.isInterpolatedMiddle ? fromScene.group: */toScene.group, - datum: toScene.group ? null : toScene.datum - }); - - interScene.dataIndex = toScene.dataIndex; - interScene.vars.category = toScene.vars.category; - - var interValueVar = new pvc.visual.ValueLabelVar( - interValue, - valueDim.format(interValue), - interValue); - - interValueVar.accValue = interAccValue; - - interScene.vars.value = interValueVar; - interScene.ownerScene = toScene; - interScene.isInterpolated = toScene.isInterpolated; - interScene.isIntermediate = true; - interScene.isSingle = false; - interScene.isNull = interIsNull; - interScene.isAlone = interIsNull && toScene.isNull && fromScene.isNull; - interScene.basePosition = interBasePosition; - interScene.orthoPosition = orthoZero; - interScene.orthoLength = orthoScale(interAccValue) - orthoZero; - - colorVarHelper.onNewScene(interScene, /* isLeaf */ true); - - return interScene; - } - - function trimNullSeriesScenes(seriesScene) { - - var seriesScenes = seriesScene.childNodes, - L = seriesScenes.length; - - // from beginning - var scene, siblingScene; - while(L && (scene = seriesScenes[0]).isNull) { - - // Don't remove the intermediate dot before the 1st non-null dot - siblingScene = scene.nextSibling; - if(siblingScene && !siblingScene.isNull){ - break; - } - - seriesScene.removeAt(0); - L--; - } - - // from end - while(L && (scene = seriesScenes[L - 1]).isNull) { - - // Don't remove the intermediate dot after the last non-null dot - siblingScene = scene.previousSibling; - if(siblingScene && !siblingScene.isNull){ - break; - } - - seriesScene.removeAt(L - 1); - L--; - } - } - } -}); diff --git a/pacotes/ccc2/pvc/pvcTitlePanel.js b/pacotes/ccc2/pvc/pvcTitlePanel.js deleted file mode 100755 index e993352..0000000 --- a/pacotes/ccc2/pvc/pvcTitlePanel.js +++ /dev/null @@ -1,28 +0,0 @@ - -def -.type('pvc.TitlePanel', pvc.TitlePanelAbstract) -.init(function(chart, parent, options){ - - if(!options){ - options = {}; - } - - var isV1Compat = chart.compatVersion() <= 1; - if(isV1Compat){ - var size = options.titleSize; - if(size == null){ - options.titleSize = 25; - } - } - - // Must be done before calling base, cause it uses _getExtension - this._extensionPrefix = !chart.parent ? "title" : "smallTitle"; - - this.base(chart, parent, options); -}) -.add({ - - font: "14px sans-serif", - - defaultPaddings: 4 -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/pvcTitlePanelAbstract.js b/pacotes/ccc2/pvc/pvcTitlePanelAbstract.js deleted file mode 100755 index cfaf605..0000000 --- a/pacotes/ccc2/pvc/pvcTitlePanelAbstract.js +++ /dev/null @@ -1,210 +0,0 @@ -def -.type('pvc.TitlePanelAbstract', pvc.BasePanel) -.init(function(chart, parent, options) { - - if (!options) { - options = {}; - } - - var anchor = options.anchor || this.anchor; - - // titleSize - if (options.size == null) { - var size = options.titleSize; - if (size != null) { - // Single size (a number or a string with only one number) - // should be interpreted as meaning the orthogonal length. - options.size = new pvc.Size().setSize(size, { - singleProp: this.anchorOrthoLength(anchor) - }); - } - } - - // titleSizeMax - if (options.sizeMax == null) { - var sizeMax = options.titleSizeMax; - if (sizeMax != null) { - // Single size (a number or a string with only one number) - // should be interpreted as meaning the orthogonal length. - options.sizeMax = new pvc.Size().setSize(sizeMax, { - singleProp: this.anchorOrthoLength(anchor) - }); - } - } - - if (options.paddings == null) { - options.paddings = this.defaultPaddings; - } - - this.base(chart, parent, options); - - if (options.font === undefined) { - var extensionFont = this._getExtension('label', 'font'); - if (typeof extensionFont === 'string') { - this.font = extensionFont; - } - } -}) -.add({ - pvLabel: null, - anchor: 'top', - - title: null, - titleSize: undefined, - font: "12px sans-serif", - - defaultPaddings: 2, - - _extensionPrefix: 'title', - - /** - * @override - */ - _calcLayout: function(layoutInfo) { - - var requestSize = new pvc.Size(); - - // TODO: take textAngle, textMargin and textBaseline into account - - // Naming is for anchor = top - var a = this.anchor; - var a_width = this.anchorLength(a); - var a_height = this.anchorOrthoLength(a); - - // 2 - Small factor to avoid cropping text on either side - var textWidth = pv.Text.measure(this.title, this.font).width + 2; - var clientWidth = layoutInfo.clientSize[a_width]; - var desiredWidth = layoutInfo.desiredClientSize[a_width]; - - if (desiredWidth == null) { - desiredWidth = textWidth > clientWidth ? clientWidth : textWidth; - } else if(desiredWidth > clientWidth) { - desiredWidth = clientWidth; - } - - var lines; - if (textWidth > desiredWidth) { - lines = pvc.text.justify(this.title, desiredWidth, this.font); - } else { - lines = this.title ? [ this.title ] : []; - } - - // ------------- - - var lineHeight = pv.Text.fontHeight(this.font); - var realHeight = lines.length * lineHeight; - var availableHeight = layoutInfo.clientSize[a_height]; - - var desiredHeight = layoutInfo.desiredClientSize[a_height]; - if (desiredHeight == null) { - desiredHeight = realHeight; - } else if(desiredHeight > availableHeight) { - desiredHeight = availableHeight; - } - - if (realHeight > desiredHeight) { - // Don't show partial lines unless it is the only one left - var maxLineCount = Math.max(1, Math.floor(desiredHeight / lineHeight)); - if (lines.length > maxLineCount) { - var firstCroppedLine = lines[maxLineCount]; - - lines.length = maxLineCount; - - realHeight = desiredHeight = maxLineCount * lineHeight; - - var lastLine = lines[maxLineCount - 1] + " " + firstCroppedLine; - - lines[maxLineCount - 1] = - pvc.text.trimToWidthB( - desiredWidth, - lastLine, - this.font, - ".."); - } - } - - layoutInfo.lines = lines; - layoutInfo.topOffset = (desiredHeight - realHeight) / 2; - layoutInfo.lineSize = { - width: desiredWidth, - height: lineHeight - }; - - layoutInfo.a_width = a_width; - layoutInfo.a_height = a_height; - - requestSize[a_width] = desiredWidth; - requestSize[a_height] = desiredHeight; - - return requestSize; - }, - - /** - * @override - */ - _createCore: function(layoutInfo) { - var rootScene = this._buildScene(layoutInfo); - - // Label - var rotationByAnchor = { - top: 0, - right: Math.PI / 2, - bottom: 0, - left: -Math.PI / 2 - }; - - var textAlign = pvc.BasePanel.horizontalAlign[this.align]; - - var textAnchor = pvc.BasePanel.leftTopAnchor[this.anchor]; - - var wrapper; - if(this.compatVersion() <= 1){ - wrapper = function(v1f){ - return function(itemScene){ - return v1f.call(this); - }; - }; - } - - this.pvLabel = new pvc.visual.Label(this, this.pvPanel, { - extensionId: 'label', - wrapper: wrapper - }) - .lock('data', rootScene.lineScenes) - .pvMark - [textAnchor](function(lineScene){ - return layoutInfo.topOffset + - lineScene.vars.size.height / 2 + - this.index * lineScene.vars.size.height; - }) - .textAlign(textAlign) - [this.anchorOrtho(textAnchor)](function(lineScene){ - switch(this.textAlign()){ - case 'center': return lineScene.vars.size.width / 2; - case 'left': return 0; - case 'right': return lineScene.vars.size.width; - } - }) - .text(function(lineScene) { return lineScene.vars.textLines[this.index]; }) - .font(this.font) - .textBaseline('middle') // layout code does not support changing this - .textAngle(rotationByAnchor[this.anchor]) - ; - }, - - _buildScene: function(layoutInfo){ - var rootScene = new pvc.visual.Scene(null, { panel: this, group: this.chart.data }); - var textLines = layoutInfo.lines; - - rootScene.vars.size = layoutInfo.lineSize; - rootScene.vars.textLines = textLines; - - rootScene.lineScenes = def.array.create(textLines.length, rootScene); - - return rootScene; - }, - - _getExtensionId: function() { - return ''; - } -}); diff --git a/pacotes/ccc2/pvc/pvcWaterfallChart.js b/pacotes/ccc2/pvc/pvcWaterfallChart.js deleted file mode 100755 index 04cf879..0000000 --- a/pacotes/ccc2/pvc/pvcWaterfallChart.js +++ /dev/null @@ -1,182 +0,0 @@ - -/** - * WaterfallChart is the class that generates waterfall charts. - * - * The waterfall chart is an alternative to the pie chart for - * showing distributions. The advantage of the waterfall chart is that - * it possibilities to visualize sub-totals and offers more convenient - * possibilities to compare the size of categories (in a pie-chart you - * have to compare wedges that are at a different angle, which - * requires some additional processing/brainpower of the end-user). - * - * Waterfall charts are basically Bar-charts with some added - * functionality. Given the complexity of the added features this - * class has it's own code-base. However, it would be easy to - * derive a BarChart class from this class by switching off a few - * features. - * - * If you have an issue or suggestions regarding the Waterfall-charts - * please contact CvK at cde@vinzi.nl - */ -def -.type('pvc.WaterfallChart', pvc.BarAbstract) -.init(function(options){ - - this.base(options); - - var parent = this.parent; - if(parent) { - this._isFalling = parent._isFalling; - } -}) -.add({ - _animatable: true, - - _isFalling: true, - _ruleInfos: null, - _waterColor: pv.color("#1f77b4").darker(),// pv.Color.names.darkslateblue,//royalblue,seagreen, //pv.color("#808285").darker(), - - /** - * Processes options after user options and default options have been merged. - * @override - */ - _processOptionsCore: function(options){ - - // Might still affect scale calculation - options.stacked = true; - - // Doesn't work (yet?); - options.baseAxisComposite = false; - - this.base(options); - - // Not supported - options.plot2 = false; - }, - - _initPlotsCore: function(){ - var options = this.options; - - var waterPlot = new pvc.visual.WaterfallPlot(this); - - this._isFalling = waterPlot.option('Direction') === 'down'; - - this._catRole.setFlatteningMode(this._isFalling ? 'tree-pre' : 'tree-post'); - this._catRole.setFlattenRootLabel(this.plots.water.option('AllCategoryLabel')); - }, - - _initLegendScenes: function(legendPanel){ - - var waterPlot = this.plots.water; - - var extAbsId = pvc.makeExtensionAbsId('line', waterPlot.extensionPrefixes); - var strokeStyle = this._getConstantExtension(extAbsId, "strokeStyle"); - if(strokeStyle){ - this._waterColor = pv.color(strokeStyle); - } - - var rootScene = legendPanel._getBulletRootScene(); - - new pvc.visual.legend.WaterfallBulletGroupScene(rootScene, { - extensionPrefix: pvc.buildIndexedId('', 1), - label: waterPlot.option('TotalLineLabel'), - color: this._waterColor - }); - - this.base(legendPanel); - }, - - /** - * Reduce operation of category ranges, into a global range. - * - * Propagates the total value. - * - * Also creates the array of rule information {@link #_ruleInfos} - * used by the waterfall panel to draw the rules. - * - * Supports {@link #_getContinuousVisibleExtent}. - */ - _reduceStackedCategoryValueExtent: function(result, catRange, catGroup){ - /* - * That min + max are the variation of this category - * relies on the concrete base._getStackedCategoryValueExtent() implementation... - * Max always contains the sum of positives, if any, or 0 - * Min always contains the sum of negatives, if any, or 0 - * max >= 0 - * min <= 0 - */ - /* - * When falling, the first category is surely *the* global total. - * When falling, the first category must set the initial offset - * and, unlike every other category group such that _isFlattenGroup===true, - * it does contribute to the offset, and positively. - * The offset property accumulates the values. - */ - var offset; - if(!result){ - if(catRange){ - offset = catRange.min + catRange.max; - - this._ruleInfos = [{ - offset: offset, - group: catGroup, - range: catRange - }]; - - // Copy the range object - return { - min: catRange.min, - max: catRange.max, - offset: offset - }; - } - - return null; - } - - offset = result.offset; - if(this._isFalling){ - this._ruleInfos.push({ - offset: offset, - group: catGroup, - range: catRange - }); - } - - if(!catGroup._isFlattenGroup || catGroup._isDegenerateFlattenGroup){ - var dir = this._isFalling ? -1 : 1; - - offset = result.offset = offset + dir * (catRange.min + catRange.max); - - if(offset > result.max){ - result.max = offset; - } - - if(offset < result.min){ - result.min = offset; - } - } - - if(!this._isFalling){ - this._ruleInfos.push({ - offset: offset, - group: catGroup, - range: catRange - }); - } - - return result; - }, - - /* @override */ - _createPlotPanels: function(parentPanel, baseOptions){ - this.wfChartPanel = - new pvc.WaterfallPanel( - this, - parentPanel, - this.plots.water, - def.create(baseOptions, { - waterfall: this.options.waterfall - })); - } -}); diff --git a/pacotes/ccc2/pvc/pvcWaterfallPanel.js b/pacotes/ccc2/pvc/pvcWaterfallPanel.js deleted file mode 100755 index 2d7a4a1..0000000 --- a/pacotes/ccc2/pvc/pvcWaterfallPanel.js +++ /dev/null @@ -1,339 +0,0 @@ - -/** - * Waterfall chart panel. - * Specific options are: - * orientation - horizontal or vertical. Default: vertical - * valuesVisible - Show or hide bar value. Default: false - * barSizeRatio - In multiple series, percentage of inner - * band occupied by bars. Default: 0.9 (90%) - * barSizeMax - Maximum size (width) of a bar in pixels. Default: 2000 - * - * Has the following protovis extension points: - * - * chart_ - for the main chart Panel - * bar_ - for the actual bar - * barPanel_ - for the panel where the bars sit - * barLabel_ - for the main bar label - */ -def -.type('pvc.WaterfallPanel', pvc.BarAbstractPanel) -.add({ - pvWaterfallLine: null, - ruleData: null, - - /** - * Called to obtain the bar differentialControl property value. - * If it returns a function, - * that function will be called once per category, - * on the first series. - * @virtual - */ - _barDifferentialControl: function(){ - var isFalling = this.chart._isFalling; - - /* - * From protovis help: - * - * Band differential control pseudo-property. - * 2 - Drawn starting at previous band offset. Multiply values by 1. Don't update offset. - * 1 - Drawn starting at previous band offset. Multiply values by 1. Update offset. - * 0 - Reset offset to 0. Drawn starting at 0. Default. Leave offset at 0. - * -1 - Drawn starting at previous band offset. Multiply values by -1. Update offset. - * -2 - Drawn starting at previous band offset. Multiply values by -1. Don't update offset. - */ - return function(scene){ - if(isFalling && !this.index){ - // First falling bar is the main total - // Must be accounted up and update the total - return 1; - } - - var group = scene.vars.category.group; - if(group._isFlattenGroup && !group._isDegenerateFlattenGroup){ - // Groups don't update the total - // Groups, always go down, except the first falling... - return -2; - } - - return isFalling ? -1 : 1; - }; - }, - - _creating: function(){ - // Register BULLET legend prototype marks - var rootScene = this._getLegendBulletRootScene(); - if(rootScene){ - var waterfallGroupScene = rootScene.firstChild; - - if(waterfallGroupScene && !waterfallGroupScene.hasRenderer()){ - var keyArgs = { - drawRule: true, - drawMarker: false, - noSelect: true, - noHover: true, - rulePvProto: new pv.Mark() - }; - - this.extend(keyArgs.rulePvProto, 'line', {constOnly: true}); - - waterfallGroupScene.renderer( - new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs)); - } - } - }, - - _createCore: function(){ - - this.base(); - - var chart = this.chart, - isVertical = this.isOrientationVertical(), - anchor = isVertical ? "bottom" : "left", - ao = this.anchorOrtho(anchor), - ruleRootScene = this._buildRuleScene(), - orthoScale = chart.axes.ortho.scale, - orthoPanelMargin = 0.04 * (orthoScale.range()[1] - orthoScale.range()[0]), - orthoZero = orthoScale(0), - sceneOrthoScale = chart.axes.ortho.sceneScale({sceneVarName: 'value'}), - sceneBaseScale = chart.axes.base.sceneScale({sceneVarName: 'category'}), - baseScale = chart.axes.base.scale, - barWidth2 = this.barWidth/2, - barWidth = this.barWidth, - barStepWidth = this.barStepWidth, - isFalling = chart._isFalling, - waterColor = chart._waterColor - ; - - if(this.plot.option('AreasVisible')){ - var panelColors = pv.Colors.category10(); - var waterGroupRootScene = this._buildWaterGroupScene(); - - this.pvWaterfallGroupPanel = new pvc.visual.Panel(this, this.pvPanel, { - extensionId: 'group' - }) - .lock('data', waterGroupRootScene.childNodes) - .pvMark - .zOrder(-1) - .fillStyle(function(/*scene*/){ - return panelColors(0)/* panelColors(scene.vars.category.level - 1)*/.alpha(0.15); - }) - [ao](function(scene){ - var categVar = scene.vars.category; - return baseScale(categVar.leftValue) - barStepWidth / 2; - }) - [this.anchorLength(anchor)](function(scene){ - var categVar = scene.vars.category, - length = Math.abs(baseScale(categVar.rightValue) - - baseScale(categVar.leftValue )); - - return length + barStepWidth; - }) - [anchor](function(scene){ - return orthoScale(scene.vars.value.bottomValue) - orthoPanelMargin/2; - }) - [this.anchorOrthoLength(anchor)](function(scene){ - return orthoScale(scene.vars.value.heightValue) + orthoPanelMargin; - //return chart.animate(orthoZero, orthoScale(scene.categ) - orthoZero); - }) - ; - } - - this.pvBar - .sign - .override('baseColor', function(type){ - var color = this.base(type); - if(type === 'fill'){ - if(!this.scene.vars.category.group._isFlattenGroup){ - return pv.color(color).alpha(0.5); - } -// else { -// return pv.color(color).darker(); -// } - } - - return color; - }) - ; - - this.pvWaterfallLine = new pvc.visual.Rule(this, this.pvPanel, { - extensionId: 'line', - noTooltip: false, - noHover: false, - noSelect: false, - noClick: false, - noDoubleClick: false - }) - .lock('data', ruleRootScene.childNodes) - .optional('visible', function(){ - return ( isFalling && !!this.scene.previousSibling) || - (!isFalling && !!this.scene.nextSibling); - }) - .optional(anchor, function(){ - return orthoZero + chart.animate(0, sceneOrthoScale(this.scene) - orthoZero); - }) - .optional(this.anchorLength(anchor), barStepWidth + barWidth) - .optional(ao, - isFalling ? - function(){ return sceneBaseScale(this.scene) - barStepWidth - barWidth2; } : - function(){ return sceneBaseScale(this.scene) - barWidth2; }) - .override('defaultColor', function(){ return waterColor; }) - .pvMark - .antialias(true) - .lineCap('butt') - ; - - if(this.plot.option('TotalValuesVisible')){ - this.pvWaterfallLabel = new pvc.visual.Label( - this, - this.pvWaterfallLine, - { - extensionId: 'lineLabel' - }) - .intercept('visible', function(scene){ - if(scene.vars.category.group._isFlattenGroup){ - return false; - } - - return isFalling || !!scene.nextSibling; - }) - .pvMark - [anchor](function(scene){ - return orthoZero + chart.animate(0, sceneOrthoScale(scene) - orthoZero); - }) - [this.anchorOrtho(anchor)](sceneBaseScale) - .textAlign(isVertical ? 'center' : 'left') - .textBaseline(function(categScene){ - if(!isVertical){ - return 'middle'; - } - - var direction = categScene.vars.direction; - if(direction == null){ - return 'bottom'; - } - - var isRising = !isFalling; - return (isRising === (direction === 'up') ? 'bottom' : 'top'); - }) - .textStyle(pv.Color.names.darkgray.darker(2)) - .textMargin(5) - .text(function(scene){ return scene.vars.value.label; }); - } - }, - - _buildRuleScene: function(){ - var rootScene = new pvc.visual.Scene(null, {panel: this, group: this.visibleData()}); - var prevValue; - - /** - * Create starting scene tree - */ - if(this.chart._ruleInfos){ - this.chart._ruleInfos - .forEach(createCategScene, this); - } - - return rootScene; - - function createCategScene(ruleInfo){ - var categData1 = ruleInfo.group; - - var categScene = new pvc.visual.Scene(rootScene, {group: categData1}); - - var categVar = - categScene.vars.category = - pvc.visual.ValueLabelVar.fromComplex(categData1); - - categVar.group = categData1; - - var value = ruleInfo.offset; - - categScene.vars.value = new pvc.visual.ValueLabelVar( - value, - this.chart._valueDim.format(value)); - - categScene.vars.direction = - (prevValue == null || prevValue === value) ? null : (prevValue < value ? 'up' : 'down'); - - prevValue = value; - } - }, - - _buildWaterGroupScene: function(){ - var chart = this.chart, - ruleInfos = this.chart._ruleInfos, - ruleInfoByCategKey = ruleInfos && def.query(ruleInfos) - .object({ - name: function(ruleInfo){ return ruleInfo.group.absKey; }, - value: function(ruleInfo){ return ruleInfo; } - }), - isFalling = chart._isFalling, - rootCatData = chart._catRole.select( - chart.partData(this.dataPartValue), - {visible: true}), - rootScene = new pvc.visual.Scene(null, {panel: this, group: rootCatData}); - - if(ruleInfoByCategKey){ - createCategSceneRecursive(rootCatData, 0); - } - - return rootScene; - - function createCategSceneRecursive(catData, level){ - var children = catData.children() - .where(function(child){ return child.key !== ""; }) - .array(); - if(children.length){ - // Group node - if(level){ - var categScene = new pvc.visual.Scene(rootScene, {group: catData}); - - var categVar = - categScene.vars.category = - pvc.visual.ValueLabelVar.fromComplex(catData); - - categVar.group = catData; - categVar.level = level; - - var valueVar = categScene.vars.value = {}; // TODO: Not A Var - var ruleInfo = ruleInfoByCategKey[catData.absKey]; - var offset = ruleInfo.offset, - range = ruleInfo.range, - height = -range.min + range.max - ; - - if(isFalling){ - var lastChild = lastLeaf(catData); - var lastRuleInfo = ruleInfoByCategKey[lastChild.absKey]; - categVar.leftValue = ruleInfo.group.value; - categVar.rightValue = lastRuleInfo.group.value; - valueVar.bottomValue = offset - range.max; - - } else { - var firstChild = firstLeaf(catData); - var firstRuleInfo = ruleInfoByCategKey[firstChild.absKey]; - categVar.leftValue = firstRuleInfo.group.value; - categVar.rightValue = ruleInfo.group.value; - valueVar.bottomValue = offset - range.max; - } - - valueVar.heightValue = height; - } - - children.forEach(function(child){ - createCategSceneRecursive(child, level + 1); - }); - } - } - - function firstLeaf(data){ - var firstChild = data._children && data._children[0]; - return firstChild ? firstLeaf(firstChild) : data; - } - - function lastLeaf(data){ - var lastChild = data._children && data._children[data._children.length - 1]; - return lastChild ? lastLeaf(lastChild) : data; - } - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/Axis.js b/pacotes/ccc2/pvc/visual/Axis.js deleted file mode 100755 index a15e5c8..0000000 --- a/pacotes/ccc2/pvc/visual/Axis.js +++ /dev/null @@ -1,219 +0,0 @@ -// Sharing this globally allows other axes sub types to inherit -// their own options defs from this one. -// A ccc-wide closure can hide this from global scope. -var axis_optionsDef; - -def.scope(function(){ - - /** - * Initializes an axis. - * - * @name pvc.visual.Axis - * - * @class Represents an axis for a role in a chart. - * - * @extends pvc.visual.OptionsBase - * - * @property {pvc.visual.Role} role The associated visual role. - * @property {pv.Scale} scale The associated scale. - * - * @constructor - * @param {pvc.BaseChart} chart The associated chart. - * @param {string} type The type of the axis. - * @param {number} [index=0] The index of the axis within its type. - * @param {object} [keyArgs] Keyword arguments. - */ - def - .type('pvc.visual.Axis', pvc.visual.OptionsBase) - .init(function(chart, type, index, keyArgs){ - - this.base(chart, type, index, keyArgs); - - // Fills #axisIndex and #typeIndex - chart._addAxis(this); - }) - .add(/** @lends pvc.visual.Axis# */{ - isVisible: true, - - // should null values be converted to zero or to the minimum value in what scale is concerned? - // 'null', 'zero', 'min', 'value' - scaleTreatsNullAs: function(){ - return 'null'; - }, - - scaleNullRangeValue: function(){ - return null; - }, - - scaleUsesAbs: function(){ - return false; - }, - - /** - * Binds the axis to a set of data cells. - * - *

- * Only after this operation is performed will - * options with a scale type prefix be found. - *

- * - * @param {object|object[]} dataCells The associated data cells. - * @type pvc.visual.Axis - */ - bind: function(dataCells){ - /*jshint expr:true */ - dataCells || def.fail.argumentRequired('dataCells'); - !this.dataCells || def.fail.operationInvalid('Axis is already bound.'); - - this.dataCells = def.array.to(dataCells); - this.dataCell = this.dataCells[0]; - this.role = this.dataCell && this.dataCell.role; - this.scaleType = groupingScaleType(this.role.grouping); - - this._checkRoleCompatibility(); - - return this; - }, - - isDiscrete: function(){ - return this.role && this.role.isDiscrete(); - }, - - isBound: function(){ - return !!this.role; - }, - - setScale: function(scale, noWrap){ - /*jshint expr:true */ - this.role || def.fail.operationInvalid('Axis is unbound.'); - - this.scale = scale ? (noWrap ? scale : this._wrapScale(scale)) : null; - - return this; - }, - - _wrapScale: function(scale){ - scale.type = this.scaleType; - - var by; - - // Applying scaleNullRangeValue to discrete scales - // Caused problems in the discrete color scales - // where we want it to catch the first color of the color scale, - // in cases where there is only a null series... - if(scale.type !== 'discrete' ){ - var useAbs = this.scaleUsesAbs(); - var nullAs = this.scaleTreatsNullAs(); - if(nullAs && nullAs !== 'null'){ - var nullValue = nullAs === 'min' ? scale.domain()[0] : 0; - - if(useAbs){ - by = function(v){ - return scale(v == null ? nullValue : (v < 0 ? -v : v)); - }; - } else { - by = function(v){ - return scale(v == null ? nullValue : v); - }; - } - } else { - var nullRangeValue = this.scaleNullRangeValue(); - if(useAbs){ - by = function(v){ - return v == null ? nullRangeValue : scale(v < 0 ? -v : v); - }; - } else { - by = function(v){ - return v == null ? nullRangeValue : scale(v); - }; - } - } - } else { - // ensure null -> "" - by = function(v){ - return scale(v == null ? '' : v); - }; - } - - // don't overwrite scale with by! it would cause infinite recursion... - return def.copy(by, scale); - }, - - /** - * Obtains a scene-scale function to compute values of this axis' main role. - * - * @param {object} [keyArgs] Keyword arguments object. - * @param {string} [keyArgs.sceneVarName] The local scene variable name by which this axis's role is known. Defaults to the role's name. - * @param {boolean} [keyArgs.nullToZero=true] Indicates that null values should be converted to zero before applying the scale. - * @type function - */ - sceneScale: function(keyArgs){ - var varName = def.get(keyArgs, 'sceneVarName') || this.role.name, - grouping = this.role.grouping; - - if(grouping.isSingleDimension && grouping.firstDimensionValueType() === Number){ - var scale = this.scale, - nullToZero = def.get(keyArgs, 'nullToZero', true); - - var by = function(scene){ - var value = scene.vars[varName].value; - if(value == null){ - if(!nullToZero){ - return value; - } - value = 0; - } - return scale(value); - }; - def.copy(by, scale); - - return by; - } - - return this.scale.by1(function(scene){ - return scene.vars[varName].value; - }); - }, - - _checkRoleCompatibility: function(){ - var L = this.dataCells.length; - if(L > 1){ - var grouping = this.role.grouping, - i; - if(this.scaleType === 'discrete'){ - for(i = 1; i < L ; i++){ - if(grouping.id !== this.dataCells[i].role.grouping.id){ - throw def.error.operationInvalid("Discrete roles on the same axis must have equal groupings."); - } - } - } else { - if(!grouping.firstDimensionType().isComparable){ - throw def.error.operationInvalid("Continuous roles on the same axis must have 'comparable' groupings."); - } - - for(i = 1; i < L ; i++){ - if(this.scaleType !== groupingScaleType(this.dataCells[i].role.grouping)){ - throw def.error.operationInvalid("Continuous roles on the same axis must have scales of the same type."); - } - } - } - } - }, - - _getOptionsDefinition: function(){ - return axis_optionsDef; - } - }); - - function groupingScaleType(grouping){ - return grouping.isDiscrete() ? - 'discrete' : - (grouping.firstDimensionValueType() === Date ? - 'timeSeries' : - 'numeric'); - } - - axis_optionsDef = { - // NOOP - }; -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/CartesianAxis.js b/pacotes/ccc2/pvc/visual/CartesianAxis.js deleted file mode 100755 index 1158711..0000000 --- a/pacotes/ccc2/pvc/visual/CartesianAxis.js +++ /dev/null @@ -1,689 +0,0 @@ -def.scope(function(){ - - var $VA = pvc.visual.Axis; - /** - * Initializes a cartesian axis. - * - * @name pvc.visual.CartesianAxis - * - * @class Represents an axis for a role in a cartesian chart. - *

- * The main properties of an axis: {@link #type}, {@link #orientation} and relevant chart's properties - * are related as follows: - *

- *
-     * axisType={base, ortho} = f(axisOrientation={x,y})
-     * 
-     *          Vertical   Horizontal   (chart orientation)
-     *         +---------+-----------+
-     *       x | base    |   ortho   |
-     *         +---------+-----------+
-     *       y | ortho   |   base    |
-     *         +---------+-----------+
-     * (axis orientation)
-     * 
- * - * @extends pvc.visual.Axis - * - * @property {pvc.CartesianAbstract} chart The associated cartesian chart. - * @property {string} type The type of the axis. One of the values: 'base' or 'ortho'. - * @property {string} orientation The orientation of the axis. - * One of the values: 'x' or 'y', for horizontal and vertical axis orientations, respectively. - * @property {string} orientedId The id of the axis with respect to the orientation and the index of the axis (""). - * - * @constructor - * @param {pvc.CartesianAbstract} chart The associated cartesian chart. - * @param {string} type The type of the axis. One of the values: 'base' or 'ortho'. - * @param {number} [index=0] The index of the axis within its type. - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.visual.Axis} for supported keyword arguments. - */ - def - .type('pvc.visual.CartesianAxis', $VA) - .init(function(chart, type, index, keyArgs){ - - var options = chart.options; - - // x, y - this.orientation = $VCA.getOrientation(type, options.orientation); - - // x, y, x2, y2, x3, y3, ... - this.orientedId = $VCA.getOrientedId(this.orientation, index); - - // secondX, secondY - if(chart._allowV1SecondAxis && index === 1){ - this.v1SecondOrientedId = 'second' + this.orientation.toUpperCase(); - } - - // id - // base, ortho, base2, ortho2, ... - - // scaleType - // discrete, continuous, numeric, timeSeries - - // common - // axis - - this.base(chart, type, index, keyArgs); - - // For now scale type is left off, - // cause it is yet unknown. - // In bind, prefixes are recalculated (see _syncExtensionPrefixes) - var extensions = this.extensionPrefixes = [ - this.id + 'Axis', - this.orientedId + 'Axis' - ]; - - if(this.v1SecondOrientedId){ - extensions.push(this.v1SecondOrientedId + 'Axis'); - } - - this._extPrefAxisPosition = extensions.length; - - extensions.push('axis'); - }) - .add(/** @lends pvc.visual.CartesianAxis# */{ - - bind: function(dataCells){ - - this.base(dataCells); - - this._syncExtensionPrefixes(); - - return this; - }, - - _syncExtensionPrefixes: function(){ - var extensions = this.extensionPrefixes; - - // remove until 'axis' (inclusive) - extensions.length = this._extPrefAxisPosition; - - var st = this.scaleType; - if(st){ - extensions.push(st + 'Axis'); // specific - if(st !== 'discrete'){ - extensions.push('continuousAxis'); // generic - } - } - - // Common - extensions.push('axis'); - }, - - setScale: function(scale){ - var oldScale = this.scale; - - this.base(scale); - - if(oldScale){ - // If any - delete this.domain; - delete this.ticks; - delete this._roundingPaddings; - } - - if(scale){ - if(!scale.isNull && this.scaleType !== 'discrete'){ - // Original data domain, before nice or tick rounding - this.domain = scale.domain(); - this.domain.minLocked = !!scale.minLocked; - this.domain.maxLocked = !!scale.maxLocked; - - if(this.scaleType === 'numeric'){ - var roundMode = this.option('DomainRoundMode'); - if(roundMode === 'nice'){ - scale.nice(); - } - - var tickFormatter = this.option('TickFormatter'); - if(tickFormatter){ - scale.tickFormatter(tickFormatter); - } - } - } - } - - return this; - }, - - setTicks: function(ticks){ - var scale = this.scale; - - /*jshint expr:true */ - (scale && !scale.isNull) || def.fail.operationInvalid("Scale must be set and non-null."); - - this.ticks = ticks; - - if(scale.type === 'numeric' && this.option('DomainRoundMode') === 'tick'){ - - delete this._roundingPaddings; - - // Commit calculated ticks to scale's domain - var tickCount = ticks && ticks.length; - if(tickCount){ - this.scale.domain(ticks[0], ticks[tickCount - 1]); - } else { - // Reset scale domain - this.scale.domain(this.domain[0], this.domain[1]); - } - } - }, - - setScaleRange: function(size){ - var scale = this.scale; - scale.min = 0; - scale.max = size; - scale.size = size; // original size // TODO: remove this... - - // ------------- - - if(scale.type === 'discrete'){ - if(scale.domain().length > 0){ // Has domain? At least one point is required to split. - var bandRatio = this.chart.options.panelSizeRatio || 0.8; - scale.splitBandedCenter(scale.min, scale.max, bandRatio); - } - } else { - scale.range(scale.min, scale.max); - } - - if(pvc.debug > 4){ - this.chart._log("Axis " + this.id + " setRange: " + pvc.stringify(scale.range())); - } - - return scale; - }, - - getScaleRoundingPaddings: function(){ - var roundingPaddings = this._roundingPaddings; - if(!roundingPaddings){ - roundingPaddings = { - begin: 0, - end: 0, - beginLocked: false, - endLocked: false - }; - - var scale = this.scale; - if(scale && !scale.isNull && scale.type !== 'discrete'){ - var originalDomain = this.domain; - - roundingPaddings.beginLocked = originalDomain.minLocked; - roundingPaddings.endLocked = originalDomain.maxLocked; - - if(scale.type === 'numeric' && this.option('DomainRoundMode') !== 'none'){ - var currDomain = scale.domain(); - var origDomain = this.domain || def.assert("Original domain must be set"); - var currLength = currDomain[1] - currDomain[0]; - if(currLength){ - // begin diff - var diff = origDomain[0] - currDomain[0]; - if(diff > 0){ - roundingPaddings.begin = diff / currLength; - } - - // end diff - diff = currDomain[1] - origDomain[1]; - if(diff > 0){ - roundingPaddings.end = diff / currLength; - } - } - } - } - - this._roundingPaddings = roundingPaddings; - } - - return roundingPaddings; - }, - - _getOptionsDefinition: function(){ - return cartAxis_optionsDef; - }, - - _buildOptionId: function(){ - return this.id + "Axis"; - }, - - _registerResolversNormal: function(rs, keyArgs){ - // II - By V1 Only Logic - if(this.chart.compatVersion() <= 1){ - rs.push(this._resolveByV1OnlyLogic); - } - - // IV - By OptionId - rs.push( - this._resolveByOptionId, - this._resolveByOrientedId); - - if(this.index === 1){ - rs.push(this._resolveByV1OptionId); - } - - rs.push( - this._resolveByScaleType, - this._resolveByCommonId); - - }, - - // xAxisOffset, yAxisOffset, x2AxisOffset - _resolveByOrientedId: pvc.options.specify(function(optionInfo){ - return this._chartOption(this.orientedId + "Axis" + optionInfo.name); - }), - - // secondAxisOffset - _resolveByV1OptionId: pvc.options.specify(function(optionInfo){ - //if(this.index === 1){ - return this._chartOption('secondAxis' + optionInfo.name); - //} - }), - - // numericAxisLabelSpacingMin - _resolveByScaleType: pvc.options.specify(function(optionInfo){ - // this.scaleType - // * discrete - // * numeric | continuous - // * timeSeries | continuous - var st = this.scaleType; - if(st){ - var name = optionInfo.name; - var value = this._chartOption(st + 'Axis' + name); - if(value === undefined && st !== 'discrete'){ - value = this._chartOption('continuousAxis' + name); - } - - return value; - } - }), - - // axisOffset - _resolveByCommonId: pvc.options.specify(function(optionInfo){ - return this._chartOption('axis' + optionInfo.name); - }) - }); - - var $VCA = pvc.visual.CartesianAxis; - - /** - * Obtains the orientation of the axis given an axis type and a chart orientation. - * - * @param {string} type The type of the axis. One of the values: 'base' or 'ortho'. - * @param {string} chartOrientation The orientation of the chart. One of the values: 'horizontal' or 'vertical'. - * - * @type string - */ - $VCA.getOrientation = function(type, chartOrientation){ - return ((type === 'base') === (chartOrientation === 'vertical')) ? 'x' : 'y'; // NXOR - }; - - /** - * Calculates the oriented id of an axis given its orientation and index. - * @param {string} orientation The orientation of the axis. - * @param {number} index The index of the axis within its type. - * @type string - */ - $VCA.getOrientedId = function(orientation, index){ - if(index === 0) { - return orientation; // x, y - } - - return orientation + (index + 1); // x2, y3, x4,... - }; - - /* PRIVATE STUFF */ - var fixedMinMaxSpec = { - resolve: '_resolveFull', - data: { - /* orthoFixedMin, orthoFixedMax */ - resolveV1: function(optionInfo){ - if(!this.index && this.type === 'ortho'){ - // Bare Id (no "Axis") - this._specifyChartOption(optionInfo, this.id + optionInfo.name); - } - return true; - } - }, - cast: pvc.castNumber - }; - - function castDomainScope(scope, axis){ - return pvc.parseDomainScope(scope, axis.orientation); - } - - function castAxisPosition(side){ - if(side){ - if(def.hasOwn(pvc.Sides.namesSet, side)){ - var mapAlign = pvc.BasePanel[this.orientation === 'y' ? 'horizontalAlign' : 'verticalAlign2']; - return mapAlign[side]; - } - - if(pvc.debug >= 2){ - pvc.log(def.format("Invalid axis position value '{0}'.", [side])); - } - } - - // Ensure a proper value - return this.orientation === 'x' ? 'bottom' : 'left'; - } - - var normalV1Data = { - resolveV1: function(optionInfo){ - if(!this.index){ - if(this._resolveByOrientedId(optionInfo)){ - return true; - } - } else if(this._resolveByV1OptionId(optionInfo)) { // secondAxis... - return true; - } - - this._resolveDefault(optionInfo); - - return true; - } - }; - - var defaultPosition = pvc.options.defaultValue(function(optionInfo){ - if(!this.typeIndex){ - return this.orientation === 'x' ? 'bottom' : 'left'; - } - - // Use the position opposite to that of the first axis - // of same orientation (the same as type) - var firstAxis = this.chart.axesByType[this.type].first; - var position = firstAxis.option('Position'); - - return pvc.BasePanel.oppositeAnchor[position]; - }); - - function castSize(value){ - var position = this.option('Position'); - return pvc.Size.toOrtho(value, position); - } - - function castTitleSize(value){ - var position = this.option('Position'); - - return pvc.Size.to(value, {singleProp: pvc.BasePanel.orthogonalLength[position]}); - } - - /*global axis_optionsDef:true*/ - var cartAxis_optionsDef = def.create(axis_optionsDef, { - Visible: { - resolve: '_resolveFull', - data: { - /* showXScale, showYScale, showSecondScale */ - resolveV1: function(optionInfo){ - if(this.index <= 1){ - var v1OptionId = this.index === 0 ? - def.firstUpperCase(this.orientation) : - 'Second'; - - this._specifyChartOption(optionInfo, 'show' + v1OptionId + 'Scale'); - } - return true; - } - }, - cast: Boolean, - value: true - }, - - /* - * 1 <- useCompositeAxis - * >= 2 <- false - */ - Composite: { - resolve: function(optionInfo){ - // Only first axis can be composite? - if(this.index > 0) { - optionInfo.specify(false); - return true; - } - - return this._resolveFull(optionInfo); - }, - data: { - resolveV1: function(optionInfo){ - this._specifyChartOption(optionInfo, 'useCompositeAxis'); - return true; - } - }, - cast: Boolean, - value: false - }, - - /* xAxisSize, - * secondAxisSize || xAxisSize - */ - Size: { - resolve: '_resolveFull', - data: normalV1Data, - cast: castSize - }, - - SizeMax: { - resolve: '_resolveFull', - cast: castSize - }, - - /* xAxisPosition, - * secondAxisPosition <- opposite(xAxisPosition) - */ - Position: { - resolve: '_resolveFull', - data: { - resolveV1: normalV1Data.resolveV1, - resolveDefault: defaultPosition - }, - cast: castAxisPosition - }, - - FixedMin: fixedMinMaxSpec, - FixedMax: fixedMinMaxSpec, - - /* 1 <- originIsZero (v1) - * 2 <- secondAxisOriginIsZero (v1 && bar) - */ - OriginIsZero: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - switch(this.index){ - case 0: - this._specifyChartOption(optionInfo, 'originIsZero'); - break; - case 1: - if(this.chart._allowV1SecondAxis){ - this._specifyChartOption(optionInfo, 'secondAxisOriginIsZero'); - } - break; - } - - return true; - } - }, - cast: Boolean, - value: true - }, - - DomainScope: { - resolve: '_resolveFull', - cast: castDomainScope, - value: 'global' - }, - - /* 1 <- axisOffset, - * 2 <- secondAxisOffset (V1 && bar) - */ - Offset: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - switch(this.index) { - case 0: - this._specifyChartOption(optionInfo, 'axisOffset'); - break; - - case 1: - if(this.chart._allowV1SecondAxis){ - this._specifyChartOption(optionInfo, 'secondAxisOffset'); - break; - } - break; - } - - return true; - } - }, - cast: pvc.castNumber - }, - - // em - LabelSpacingMin: { - resolve: '_resolveFull', - cast: pvc.castNumber - }, - - OverlappedLabelsMode: { - resolve: '_resolveFull', - cast: pvc.parseOverlappedLabelsMode, - value: 'hide' - }, - - /* RULES */ - Grid: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - if(!this.index){ - this._specifyChartOption(optionInfo, this.orientation + 'AxisFullGrid'); - } - return true; - } - }, - cast: Boolean, - value: false - }, - - GridCrossesMargin: { // experimental - resolve: '_resolveFull', - cast: Boolean, - value: true - }, - - EndLine: { // deprecated - resolve: '_resolveFull', - cast: Boolean - }, - - ZeroLine: { - resolve: '_resolveFull', - cast: Boolean, - value: true - }, - RuleCrossesMargin: { // experimental - resolve: '_resolveFull', - cast: Boolean, - value: true - }, - - /* TICKS */ - Ticks: { - resolve: '_resolveFull', - cast: Boolean - }, - DesiredTickCount: { // secondAxisDesiredTickCount (v1 && bar) - resolve: '_resolveFull', - data: { - resolveV1: normalV1Data.resolveV1, - resolveDefault: function(optionInfo){ - if(this.chart.compatVersion() <= 1){ - optionInfo.defaultValue(5); - return true; - } - } - }, - cast: pvc.castNumber - }, - MinorTicks: { - resolve: '_resolveFull', - data: normalV1Data, - cast: Boolean, - value: true - }, - TickFormatter: { - resolve: '_resolveFull', - cast: def.fun.as - }, - DomainRoundMode: { // secondAxisRoundDomain (bug && v1 && bar), secondAxisDomainRoundMode (v1 && bar) - resolve: '_resolveFull', - data: { - resolveV1: normalV1Data.resolveV1, - resolveDefault: function(optionInfo){ - if(this.chart.compatVersion() <= 1){ - optionInfo.defaultValue('none'); - return true; - } - } - }, - - cast: pvc.parseDomainRoundingMode, - value: 'tick' - }, - TickExponentMin: { - resolve: '_resolveFull', - cast: pvc.castNumber - }, - TickExponentMax: { - resolve: '_resolveFull', - cast: pvc.castNumber - }, - - /* TITLE */ - Title: { - resolve: '_resolveFull', - cast: String - }, - TitleSize: { - resolve: '_resolveFull', - cast: castTitleSize - }, - TitleSizeMax: { - resolve: '_resolveFull', - cast: castTitleSize - }, - TitleFont: { - resolve: '_resolveFull', - cast: String - }, - TitleMargins: { - resolve: '_resolveFull', - cast: pvc.Sides.as - }, - TitlePaddings: { - resolve: '_resolveFull', - cast: pvc.Sides.as - }, - TitleAlign: { - resolve: '_resolveFull', - cast: function castAlign(align){ - var position = this.option('Position'); - return pvc.parseAlign(position, align); - } - }, - - Font: { // axisLabelFont (v1 && index == 0 && HeatGrid) - resolve: '_resolveFull', - cast: String - }, - - ClickAction: { - resolve: '_resolveFull', - data: normalV1Data - }, // (v1 && index === 0) - - DoubleClickAction: { - resolve: '_resolveFull', - data: normalV1Data - } // idem - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/CartesianAxisRootScene.js b/pacotes/ccc2/pvc/visual/CartesianAxisRootScene.js deleted file mode 100755 index 433ff13..0000000 --- a/pacotes/ccc2/pvc/visual/CartesianAxisRootScene.js +++ /dev/null @@ -1,15 +0,0 @@ - -/** - * Initializes an axis root scene. - * - * @name pvc.visual.CartesianAxisRootScene - * - * @extends pvc.visual.Scene - * - * @constructor - * @param {pvc.visual.Scene} [parent] The parent scene, if any. - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.visual.Scene} for supported keyword arguments. - */ -def -.type('pvc.visual.CartesianAxisRootScene', pvc.visual.Scene); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/CartesianAxisTickScene.js b/pacotes/ccc2/pvc/visual/CartesianAxisTickScene.js deleted file mode 100755 index 743b836..0000000 --- a/pacotes/ccc2/pvc/visual/CartesianAxisTickScene.js +++ /dev/null @@ -1,24 +0,0 @@ - -/** - * Initializes an axis tick scene. - * - * @name pvc.visual.CartesianAxisTickScene - * - * @extends pvc.visual.Scene - * - * @constructor - * @param {pvc.visual.CartesianAxisRootScene} [parent] The parent scene, if any. - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.visual.Scene} for supported keyword arguments. - */ -def -.type('pvc.visual.CartesianAxisTickScene', pvc.visual.Scene) -.init(function(parent, keyArgs){ - - this.base(parent, keyArgs); - - this.vars.tick = new pvc.visual.ValueLabelVar( - def.get(keyArgs, 'tick'), - def.get(keyArgs, 'tickLabel'), - def.get(keyArgs, 'tickRaw')); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/CartesianFocusWindow.js b/pacotes/ccc2/pvc/visual/CartesianFocusWindow.js deleted file mode 100755 index 2ee4c88..0000000 --- a/pacotes/ccc2/pvc/visual/CartesianFocusWindow.js +++ /dev/null @@ -1,627 +0,0 @@ -def.scope(function(){ - - def - .type('pvc.visual.CartesianFocusWindow', pvc.visual.OptionsBase) - .init(function(chart){ - - this.base(chart, 'focusWindow', 0, {byNaked: false}); - - // TODO: ortho - var baseAxis = chart.axes.base; - this.base = new pvc.visual.CartesianFocusWindowAxis(this, baseAxis); - }) - .add(/** @lends pvc.visual.FocusWindow# */{ - _getOptionsDefinition: function(){ - return focusWindow_optionsDef; - }, - - _exportData: function(){ - return { - base: def.copyProps(this.base, pvc.visual.CartesianFocusWindow.props) - }; - }, - - _importData: function(data){ - var baseData = data.base; - - this.base.option.specify({ - Begin: baseData.begin, - End: baseData.end, - Length: baseData.length - }); - }, - - _initFromOptions: function(){ - this.base._initFromOptions(); - }, - - _onAxisChanged: function(axis){ - // Fire event - var changed = this.option('Changed'); - if(changed){ - changed.call(this.chart.basePanel._getContext()); - } - } - }); - - var focusWindow_optionsDef = def.create(axis_optionsDef, { - Changed: { - resolve: '_resolveFull', - cast: def.fun.as - } - }); - - def - .type('pvc.visual.CartesianFocusWindowAxis', pvc.visual.OptionsBase) - .init(function(fw, axis){ - this.window = fw; - this.axis = axis; - this.isDiscrete = axis.isDiscrete(); - - // focusWindowBase/Ortho - this.base( - axis.chart, - 'focusWindow' + def.firstUpperCase(axis.type), - 0, - {byNaked: false}); - }) - .addStatic({ - props: ['begin', 'end', 'length'] - }) - .add(/** @lends pvc.visual.FocusWindow# */{ - _getOptionsDefinition: function(){ - return focusWindowAxis_optionsDef; - }, - - _initFromOptions: function(){ - var o = this.option; - this.set({ - begin: o('Begin' ), - end: o('End' ), - length: o('Length') - }); - }, - - set: function(keyArgs){ - var me = this; - - var render = def.get(keyArgs, 'render'); - var select = def.get(keyArgs, 'select', true); - - var b, e, l; - keyArgs = me._readArgs(keyArgs); - if(!keyArgs){ - if(this.begin != null && this.end != null && this.length != null){ - return; - } - } else { - b = keyArgs.begin; - e = keyArgs.end; - l = keyArgs.length; - } - - var axis = me.axis; - var scale = axis.scale; - var isDiscrete = me.isDiscrete; - var contCast = !isDiscrete ? axis.role.firstDimensionType().cast : null; - var domain = scale.domain(); - - var a, L; - if(isDiscrete){ - L = domain.length; - var ib, ie, ia; - if(b != null){ - var nb = +b; - if(!isNaN(nb)){ - if(nb === Infinity){ - ib = L - 1; - b = domain[ib]; - } else if(nb === -Infinity){ - ib = 0; - b = domain[ib]; - } - } - - if(ib == null){ - ib = domain.indexOf(''+b); - if(ib < 0){ - //b = null; - ib = 0; - b = domain[ib]; - } - } - } - - if(e != null){ - var ne = +e; - if(!isNaN(ne)){ - if(ne === Infinity){ - ie = L - 1; - e = domain[ie]; - } else if(ne === -Infinity){ - ie = 0; - e = domain[ie]; - } - } - - if(ie == null){ - ie = domain.indexOf(''+e); - if(ie < 0){ - //e = null; - ie = L - 1; - e = domain[ie]; - } - } - } - - if(l != null){ - l = +l; - if(isNaN(l)){ - l = null; - } else if(l < 0 && (b != null || e != null)) { - // Switch b and e - a = b; - ia = ib; - b = e, ib = ie, e = a, ie = ia; - l = -l; - } - - // l > L ?? - } - - if(b != null){ - if(e != null){ - if(ib > ie){ - // Switch b and e - a = b; - ia = ib; - b = e, ib = ie, e = a, ie = ia; - } - // l is ignored - l = ie - ib + 1; - } else { - // b && !e - if(l == null){ - // to the end of the domain? - l = L - ib; - } - - ie = ib + l - 1; - if(ie > L - 1){ - ie = L - 1; - l = ie - ib + 1; - } - - e = domain[ie]; - } - } else { - // !b - if(e != null){ - // !b && e - if(l == null){ - // from the beginning of the domain? - l = ie; - // ib = 0 - } - - ib = ie - l + 1; - if(ib < 0){ - ib = 0; - l = ie - ib + 1; - } - - b = domain[ib]; - } else { - // !b && !e - if(l == null){ - l = Math.max(~~(L / 3), 1); // 1/3 of the width? - } - - if(l > L){ - l = L; - ib = 0; - ie = L - 1; - } else { - // ~~ <=> Math.floor for x >= 0 - ia = ~~(L / 2); // window center - ib = ia - ~~(l/2); - ie = ib + l - 1; - } - - b = domain[ib]; - e = domain[ie]; - } - } - - } else { - // Continuous - - if(l != null){ - l = +l; - if(isNaN(l)){ - l = null; - } else if(l < 0 && (b != null || e != null)) { - // Switch b and e - a = b; - b = e, e = a; - l = -l; - } - - // l > L ?? - } - - var min = domain[0]; - var max = domain[1]; - L = max - min; - if(b != null){ - // -Infinity is a placeholder for min - if(b < min){ - b = min; - } - - // +Infinity is a placeholder for max - if(b > max){ - b = max; - } - } - - if(e != null){ - // -Infinity is a placeholder for min - if(e < min){ - e = min; - } - - // +Infinity is a placeholder for max - if(e > max){ - e = max; - } - } - - if(b != null){ - if(e != null){ - if(b > e){ - // Switch b and e - a = b; - b = e, e = a; - } - l = e - b; - } else { - // b && !e - if(l == null){ - // to the end of the domain? - l = max - b; - } - - e = b + l; - if(e > max){ - e = max; - l = e - b; - } - } - } else { - // !b - if(e != null){ - // !b && e - if(l == null){ - // from the beginning of the domain? - l = e - min; - // b = min - } - - b = e - l; - if(b < min){ - b = min; - l = e - b; - } - } else { - // !b && !e - if(l == null){ - l = Math.max(~~(L / 3), 1); // 1/3 of the width? - } - - if(l > L){ - l = L; - b = min; - e = max; - } else { - // ~~ <=> Math.floor for x >= 0 - a = ~~(L / 2); // window center - b = a - ~~(l/2); - e = (+b) + (+l); // NOTE: Dates subtract, but don't add... - } - } - } - - b = contCast(b); - e = contCast(e); - l = contCast(l); - - var constraint = me.option('Constraint'); - if(constraint){ - var oper2 = { - type: 'new', - target: 'begin', - value: b, - length: l, - length0: l, - min: min, - max: max, - minView: min, - maxView: max - }; - - constraint(oper2); - - b = contCast(oper2.value ); - l = contCast(oper2.length); - e = contCast((+b) + (+l)); // NOTE: Dates subtract, but don't add... - } - } - - me._set(b, e, l, select, render); - }, - - _updatePosition: function(pbeg, pend, select, render){ - var me = this; - var axis = me.axis; - var scale = axis.scale; - - var b, e, l; - - if(me.isDiscrete){ - var ib = scale.invertIndex(pbeg); - var ie = scale.invertIndex(pend) - 1; - var domain = scale.domain(); - - b = domain[ib]; - e = domain[ie]; - l = ie - ib + 1; - } else { - b = scale.invert(pbeg); - e = scale.invert(pend); - l = e - b; - } - - this._set(b, e, l, select, render); - }, - - /* - var oper = { - type: op, - target: target, - point: p, - length: l, // new length - length0: l0, // prev length - min: drag.min[a_p], - max: drag.max[a_p], - minView: 0, - maxView: w - }; - */ - _constraintPosition: function(oper){ - var me = this; - var axis = me.axis; - var scale = axis.scale; - var constraint; - - if(me.isDiscrete){ - // Align to category boundaries - var index = Math.floor(scale.invertIndex(oper.point, /* noRound */true)); - if(index >= 0){ - var r = scale.range(); - var L = scale.domain().length; - var S = (r.max - r.min) / L; - if(index >= L && (oper.type === 'new' || oper.type === 'resize-begin')){ - index = L - 1; - } - oper.point = index * S; - } - } else if((constraint = me.option('Constraint'))){ - var contCast = axis.role.firstDimensionType().cast; - var v = contCast(scale.invert(oper.point)); - - var sign = oper.target === 'begin' ? 1 : -1; - - var pother = oper.point + sign * oper.length; - var vother = contCast(scale.invert(pother)); - var vlength = contCast(sign * (vother - v)); - - var vlength0, pother0, vother0; - if(oper.length === oper.length0){ - vlength0 = vlength; - } else { - pother0 = oper.point + sign * oper.length0; - vother0 = contCast(scale.invert(pother0)); - vlength0 = sign * (vother0 - v); - } - - var vmin = contCast(scale.invert(oper.min)); - var vmax = contCast(scale.invert(oper.max)); - - var oper2 = { - type: oper.type, - target: oper.target, - value: v, - length: vlength, // new length if value is accepted - length0: vlength0, // prev length (with previous value) - min: vmin, - max: vmax, - minView: contCast(scale.invert(oper.minView)), - maxView: contCast(scale.invert(oper.maxView)) - }; - - constraint(oper2); - - // detect any changes and update oper - if(+oper2.value !== +v){ - v = oper2.value; - oper.point = scale(v); - } - - var vlength2 = oper2.length; - if(+vlength2 !== +vlength){ - if(+vlength2 === +vlength0){ - oper.length = oper.length0; - } else { - var vother2 = (+v) + sign * (+vlength2); // NOTE: Dates subtract, but don't add... - var pother2 = scale(vother2); - - oper.length = pother2 - sign * oper.point; - } - } - - if(+oper2.min !== +vmin){ - oper.min = scale(oper2.min); - } - - if(+oper2.max !== +vmax){ - oper.max = scale(oper2.max); - } - } - }, - - _compare: function(a, b){ - return this.isDiscrete ? - (('' + a) === ('' + b)) : - ((+a) === (+b)); - }, - - _set: function(b, e, l, select, render){ - var me = this; - var changed = false; - - if(!me._compare(b, me.begin)){ - me.begin = b; - changed = true; - } - - if(!me._compare(e, me.end)){ - me.end = e; - changed = true; - } - - if(!me._compare(l, me.length)){ - me.length = l; - changed = true; - } - - if(changed){ - me.window._onAxisChanged(this); - } - - if(select){ - me._updateSelection({render: render}); - } - - return changed; - }, - - _readArgs: function(keyArgs){ - if(keyArgs){ - var out = {}; - var any = 0; - - var read = function(p){ - var v = keyArgs[p]; - if(v != null){ - any = true; - } else { - v = this[p]; - } - - out[p] = v; - }; - - pvc.visual.CartesianFocusWindowAxis.props.forEach(read, this); - - if(any){ - return out; - } - } - }, - - // keyArgs: render: boolean [true] - _updateSelection: function(keyArgs){ - var me = this; - - // TODO: Only the first dataCell is supported... - // TODO: cache domainData? - - var selectDatums; - var axis = me.axis; - var isDiscrete = axis.isDiscrete(); - var chart = axis.chart; - var dataCell = axis.dataCell; - var role = dataCell.role; - var partData = chart.partData(dataCell.dataPartValue, {visible: true}); - var domainData; - if(isDiscrete){ - domainData = partData.flattenBy(role); - - var dataBegin = domainData._childrenByKey[me.begin]; - var dataEnd = domainData._childrenByKey[me.end ]; - if(dataBegin && dataEnd){ - var indexBegin = dataBegin.childIndex(); - var indexEnd = dataEnd .childIndex(); - selectDatums = def - .range(indexBegin, indexEnd - indexBegin + 1) - .select(function(index){ return domainData._children[index]; }) - .selectMany(function(data){ return data._datums; }) - .distinct(function(datum){ return datum.key; }) - ; - } - } else { - domainData = partData; - - var dimName = role.firstDimensionName(); - selectDatums = def - .query(partData._datums) - .where(function(datum){ - var v = datum.atoms[dimName].value; - return v != null && v >= me.begin && v <= me.end; - }); - } - - if(selectDatums){ - chart.data.replaceSelected(selectDatums); - - // Fire events; maybe render (keyArgs) - chart.root.updateSelections(keyArgs); - } - } - }); - - - /*global axis_optionsDef:true*/ - var focusWindowAxis_optionsDef = def.create(axis_optionsDef, { - Resizable: { - resolve: '_resolveFull', - cast: Boolean, - value: true - }, - - Movable: { - resolve: '_resolveFull', - cast: Boolean, - value: true - }, - - Begin: { - resolve: '_resolveFull' - }, - - End: { - resolve: '_resolveFull' - }, - - Length: { - resolve: '_resolveFull' - }, - - // Continuous Axis function(v, vother, op, vmax) -> vconstrained - Constraint: { - resolve: '_resolveFull', - cast: def.fun.as - } - }); -}); diff --git a/pacotes/ccc2/pvc/visual/ColorAxis.js b/pacotes/ccc2/pvc/visual/ColorAxis.js deleted file mode 100755 index 184c752..0000000 --- a/pacotes/ccc2/pvc/visual/ColorAxis.js +++ /dev/null @@ -1,551 +0,0 @@ -def.scope(function(){ - - /** - * Initializes a color axis. - * - * @name pvc.visual.ColorAxis - * - * @class Represents an axis that maps colors to the values of a role. - * - * @extends pvc.visual.Axis - */ - def - .type('pvc.visual.ColorAxis', pvc.visual.Axis) - .add(/** @lends pvc.visual.ColorAxis# */{ - - scaleNullRangeValue: function(){ - return this.option('Missing') || null; - }, - - scaleUsesAbs: function(){ - return this.option('UseAbs'); - }, - - bind: function(dataCells){ - this.base(dataCells); - - // -- collect distinct plots - // Transform depends on this - // Colors depends on Transform - this._plotList = - def - .query(dataCells) - .select(function(dataCell){ return dataCell.plot; }) - .distinct(function(plot){ return plot && plot.id; }) - .array() - ; - - return this; - }, - - calculateScale: function(){ - /*jshint expr:true */ - var scale, noWrap; - var dataCells = this.dataCells; - if(dataCells){ - var chart = this.chart; - if(this.scaleType === 'discrete'){ - var domainValues = - def - .query(dataCells) - .selectMany(function(dataCell){ - var role = dataCell.role; - if(role && role.isBound()){ - // Visible and not visible! - var partData = chart.partData(dataCell.dataPartValue); - var domainData = partData && partData.flattenBy(role); - - dataCell.data = domainData; - - return domainData && domainData.children(); - } - }) - .distinct(function(child){ return child.key; }) - .select(function(child){ return def.nullyTo(child.value, ''); }) - .array() - ; - - this.domainValues = domainValues; - - // Call the transformed color scheme with the domain values - // to obtain a final scale object - scale = this.scheme()(domainValues); - - // scale is already wrapped by this axis' _wrapScale - noWrap = true; - } else { - if(dataCells.length === 1){ - // Local scope: - // Visible only! -// var visibleDomainData = -// chart -// .partData(this.dataCell.dataPartValue) -// .flattenBy(this.role, {visible: true}) -// ; - - var visibleDomainData = chart.root.visibleData(this.dataCell.dataPartValue); - var normByCateg = this.option('NormByCategory'); - var scaleOptions = { - type: this.option('ScaleType'), - colors: this.option('Colors')().range(), // obtain the underlying colors array - colorDomain: this.option('Domain'), - colorMin: this.option('Min'), - colorMax: this.option('Max'), - colorNull: this.option('Missing'), // TODO: already handled by the axis wrapping - data: visibleDomainData, - colorDimension: this.role.firstDimensionName(), - normPerBaseCategory: normByCateg - }; - - if(normByCateg){ - this.scalesByCateg = pvc.color.scales(scaleOptions); - } else { - scale = pvc.color.scale(scaleOptions); - } - } - } - } - - this.setScale(scale, noWrap); - - return this; - }, - - // Called from within setScale - _wrapScale: function(scale){ - // Check if there is a color transform set - // and if so, transform the color scheme - // If the user specified the colors, - // do not apply default color transforms... - var applyTransf; - if(this.scaleType === 'discrete'){ - applyTransf = this.option.isSpecified('Transform') || - (!this.option.isSpecified('Colors') && - !this.option.isSpecified('Map' )); - } else { - applyTransf = true; - } - - if(applyTransf){ - var colorTransf = this.option('Transform'); - if(colorTransf){ - scale = scale.transform(colorTransf); - } - } - - return this.base(scale); - }, - - scheme: function(){ - return def.lazy(this, '_scheme', this._createScheme, this); - }, - - _createColorMapFilter: function(colorMap){ - // Fixed Color Values (map of color.key -> first domain value of that color) - var fixedColors = def.uniqueIndex(colorMap, function(c){ return c.key; }); - - return { - domain: function(k){ - return !def.hasOwn(colorMap, k); - }, - - color: function(c){ - return !def.hasOwn(fixedColors, c.key); - } - }; - }, - - _createScheme: function(){ - var me = this; - var baseScheme = me.option('Colors'); - - if(me.scaleType !== 'discrete'){ - // TODO: this implementation doesn't support NormByCategory... - return function(d/*domainAsArrayOrArgs*/){ - // Create a fresh baseScale, from the baseColorScheme - // Use baseScale directly - var scale = baseScheme.apply(null, arguments); - - // Apply Transforms, nulls, etc, according to the axis' rules - return me._wrapScale(scale); - }; - } - - var colorMap = me.option('Map'); // map domain key -> pv.Color - if(!colorMap){ - return function(d/*domainAsArrayOrArgs*/){ - // Create a fresh baseScale, from the baseColorScheme - // Use baseScale directly - var scale = baseScheme.apply(null, arguments); - - // Apply Transforms, nulls, etc, according to the axis' rules - return me._wrapScale(scale); - }; - } - - var filter = this._createColorMapFilter(colorMap); - - return function(d/*domainAsArrayOrArgs*/){ - - // Create a fresh baseScale, from the baseColorScheme - var scale; - if(!(d instanceof Array)){ - d = def.array.copy(arguments); - } - - // Filter the domain before creating the scale - d = d.filter(filter.domain); - - var baseScale = baseScheme(d); - - // Removed fixed colors from the baseScale - var r = baseScale.range().filter(filter.color); - - baseScale.range(r); - - // Intercept so that the fixed color is tested first - scale = function(k){ - var c = def.getOwn(colorMap, k); - return c || baseScale(k); - }; - - def.copy(scale, baseScale); - - // override domain and range methods - var dx, rx; - scale.domain = function(){ - if (arguments.length) { - throw def.operationInvalid("The scale cannot be modified."); - } - if(!dx){ - dx = def.array.append(def.ownKeys(colorMap), d); - } - return dx; - }; - - scale.range = function(){ - if (arguments.length) { - throw def.operationInvalid("The scale cannot be modified."); - } - if(!rx){ - rx = def.array.append(def.own(colorMap), d); - } - return rx; - }; - - // At last, apply Transforms, nulls, etc, according to the axis' rules - return me._wrapScale(scale); - }; - }, - - sceneScale: function(keyArgs){ - var varName = def.get(keyArgs, 'sceneVarName') || this.role.name; - - return this.scale.by1(function(scene){ - return scene.vars[varName].value; - }); - }, - - _buildOptionId: function(){ - return this.id + "Axis"; - }, - - _getOptionsDefinition: function(){ - return colorAxis_optionsDef; - }, - - _resolveByNaked: pvc.options.specify(function(optionInfo){ - // The first of the type receives options without the "Axis" suffix. - if(!this.index){ - return this._chartOption(this.id + def.firstUpperCase(optionInfo.name)); - } - }), - - _specifyV1ChartOption: function(optionInfo, asName){ - if(!this.index && - this.chart.compatVersion() <= 1 && - this._specifyChartOption(optionInfo, asName)){ - return true; - } - } - }); - - /* PRIVATE STUFF */ - function castSize(size){ - // Single size or sizeMax (a number or a string) - // should be interpreted as meaning the orthogonal length. - - if(!def.object.is(size)){ - var position = this.option('Position'); - size = new pvc.Size() - .setSize(size, { - singleProp: pvc.BasePanel.orthogonalLength[position] - }); - } - - return size; - } - - function castAlign(align){ - var position = this.option('Position'); - return pvc.parseAlign(position, align); - } - - function castColorMap(colorMap){ - var resultMap; - if(colorMap){ - var any; - def.eachOwn(colorMap, function(v, k){ - any = true; - colorMap[k] = pv.color(v); - }); - - if(any){ - resultMap = colorMap; - } - } - - return resultMap; - } - - var legendData = { - resolveDefault: function(optionInfo){ - // Naked - if(!this.index && - this._specifyChartOption(optionInfo, def.firstLowerCase(optionInfo.name))){ - return true; - } - } - }; - - function getDefaultColor(optionInfo){ - var colors; - if(this.scaleType === 'discrete'){ - if(this.index === 0){ - // Assumes default pvc scale - colors = pvc.createColorScheme(); - } else { - // Use colors of axes with own colors. - // Use a color scheme that always returns - // the global color scale of the role - var me = this; - colors = function(){ // ignore domain values - return me.chart._getRoleColorScale(me.role.name); - }; - } - } else { - colors = ['red', 'yellow','green'] - .map(function(name){ return pv.Color.names[name]; }); - } - - return colors; - } - - - /*global axis_optionsDef:true*/ - var colorAxis_optionsDef = def.create(axis_optionsDef, { - /* - * colors (special case) - * colorAxisColors - * color2AxisColors - * color3AxisColors - * - * ----- - * secondAxisColor (V1 compatibility) - */ - Colors: { - resolve: '_resolveFull', - getDefault: getDefaultColor, - data: { - resolveV1: function(optionInfo){ - if(this.scaleType === 'discrete'){ - if(this.index === 0){ - this._specifyChartOption(optionInfo, 'colors'); - } else if(this.index === 1 && this.chart._allowV1SecondAxis) { - this._specifyChartOption(optionInfo, 'secondAxisColor'); - } - } else { - this._specifyChartOption(optionInfo, 'colorRange'); - } - - return true; - }, - resolveDefault: function(optionInfo){ // after normal resolution - // Handle naming exceptions - if(this.index === 0){ - this._specifyChartOption(optionInfo, 'colors'); - } - } - }, - cast: pvc.colorScheme - }, - - /** - * For ordinal color scales, a map of keys and their fixed colors. - * - * @example - *
-         *  {
-         *      'Lisbon': 'red',
-         *      'London': 'blue'
-         *  }
-         * 
- */ - Map: { - resolve: '_resolveFull', - cast: castColorMap - }, - - /* - * A function that transforms the colors - * of the color scheme: - * pv.Color -> pv.Color - */ - Transform: { - resolve: '_resolveFull', - data: { - resolveDefault: function(optionInfo){ - var plotList = this._plotList; - if(plotList.length <= 2){ - var onlyTrendAndPlot2 = - def - .query(plotList) - .all(function(plot){ - var name = plot.name; - return (name === 'plot2' || name === 'trend'); - }); - - if(onlyTrendAndPlot2){ - optionInfo.defaultValue(pvc.brighterColorTransform); - return true; - } - } - } - }, - cast: def.fun.to - }, - - NormByCategory: { - resolve: function(optionInfo){ - if(!this.chart._allowColorPerCategory){ - optionInfo.specify(false); - return true; - } - - return this._resolveFull(optionInfo); - }, - data: { - resolveV1: function(optionInfo){ - this._specifyV1ChartOption(optionInfo, 'normPerBaseCategory'); - return true; - } - }, - cast: Boolean, - value: false - }, - - // ------------ - // Continuous color scale - ScaleType: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - this._specifyV1ChartOption(optionInfo, 'scalingType'); - return true; - } - }, - cast: pvc.parseContinuousColorScaleType, - value: 'linear' - }, - - UseAbs: { - resolve: '_resolveFull', - cast: Boolean, - value: false - }, - - Domain: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - this._specifyV1ChartOption(optionInfo, 'colorRangeInterval'); - return true; - } - }, - cast: def.array.to - }, - - Min: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - this._specifyV1ChartOption(optionInfo, 'minColor'); - return true; - } - }, - cast: pv.color - }, - - Max: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - this._specifyV1ChartOption(optionInfo, 'maxColor'); - return true; - } - }, - cast: pv.color - }, - - Missing: { // Null, in lower case is reserved in JS... - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - this._specifyV1ChartOption(optionInfo, 'nullColor'); - return true; - } - }, - cast: pv.color, - value: pv.color("#efc5ad") - }, - - // ------------ - - /* - * LegendVisible - */ - LegendVisible: { - resolve: '_resolveFull', - data: legendData, - cast: Boolean, - value: true - }, - - LegendClickMode: { - resolve: '_resolveFull', - data: legendData, - cast: pvc.parseLegendClickMode, - value: 'toggleVisible' - }, - - LegendDrawLine: { - resolve: '_resolveFull', - data: legendData, - cast: Boolean, - value: false - }, - - LegendDrawMarker: { - resolve: '_resolveFull', - data: legendData, - cast: Boolean, - value: true - }, - - LegendShape: { - resolve: '_resolveFull', - data: legendData, - cast: pvc.parseShape - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/Context.js b/pacotes/ccc2/pvc/visual/Context.js deleted file mode 100755 index 12b344a..0000000 --- a/pacotes/ccc2/pvc/visual/Context.js +++ /dev/null @@ -1,129 +0,0 @@ -/** - * Initializes a visual context. - * - * @name pvc.visual.Context - * - * @class Represents a visualization context. - * The visualization context gives access to all relevant information - * for rendering or interacting with a visualization. - *

- * A visualization context object may be reused - * across extension points invocations and actions. - *

- * - * @property {pvc.BaseChart} chart The chart instance. - * @property {pvc.BasePanel} panel The panel instance. - * @property {number} index The render index. - * @property {pvc.visual.Scene} scene The render scene. - * @property {object} event An event object, present when a click or double-click action is being processed. - * @property {pv.Mark} pvMark The protovis mark. - * - * @constructor - * @param {pvc.BasePanel} panel The panel instance. - * @param {pv.Mark} mark The protovis mark. - * @param {object} [event] An event object. - */ -def.type('pvc.visual.Context') -.init(function(panel, mark, event){ - this.chart = panel.chart; - this.panel = panel; - - visualContext_update.call(this, mark, event); -}) -.add(/** @lends pvc.visual.Context */{ - isPinned: false, - - pin: function(){ - this.isPinned = true; - return this; - }, - - finished: function(v){ - /*jshint sub:true */ - return this.sign.finished(v); - }, - - delegate: function(dv){ - return this.sign.delegate(dv); - }, - - /* V1 DIMENSION ACCESSORS */ - getV1Series: function(){ - var s; - var series = this.scene.firstAtoms && (s = this.scene.firstAtoms[this.panel._getV1DimName('series')]) && s.rawValue; - if(series == null){ - series = 'Series'; - } - - return series; - }, - - getV1Category: function(){ - var c; - return this.scene.firstAtoms && (c = this.scene.firstAtoms[this.panel._getV1DimName('category')]) && c.rawValue; - }, - - getV1Value: function(){ - var v; - return this.scene.firstAtoms && (v = this.scene.firstAtoms[this.panel._getV1DimName('value')]) && v.value; - }, - - getV1Datum: function(){ - return this.panel._getV1Datum(this.scene); - } -}); - -if(Object.defineProperty){ - try{ - Object.defineProperty(pvc.visual.Context.prototype, 'parent', { - get: function(){ - throw def.error.operationInvalid("The 'this.parent.index' idiom has no equivalent in this version. Please try 'this.pvMark.parent.index'."); - } - }); - } catch(ex) { - /* IE THROWS */ - } -} - -/** - * Used internally to update a visual context. - * - * @name pvc.visual.Context#_update - * @function - * @param {pv.Mark} mark The protovis mark being rendered or targeted by an event. - * @param {object} [event] An event object. - * @type undefined - * @private - * @virtual - * @internal - */ -function visualContext_update(mark, event){ - - this.event = event || null; - this.pvMark = mark; - - var scene; - if(mark){ - var sign = this.sign = mark.sign || null; - if(sign){ - scene = mark.instance().data; - } - - if(!scene){ - this.index = null; - scene = new pvc.visual.Scene(null, {panel: this.panel}); - } else { - this.index = scene.childIndex(); - } - } else { - this.sign = null; - this.index = null; - - scene = new pvc.visual.Scene(null, { - panel: this.panel, - group: this.chart.root.data - }); - } - - this.scene = scene; -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/Legend.js b/pacotes/ccc2/pvc/visual/Legend.js deleted file mode 100755 index 2e5a1a0..0000000 --- a/pacotes/ccc2/pvc/visual/Legend.js +++ /dev/null @@ -1,121 +0,0 @@ -def.scope(function(){ - - /** - * Initializes a legend. - * - * @name pvc.visual.Legend - * - * @class Manages the options of a chart legend. - * @extends pvc.visual.OptionsBase - */ - def - .type('pvc.visual.Legend', pvc.visual.OptionsBase) - .init(function(chart, type, index, keyArgs){ - // prevent naked resolution of legend - keyArgs = def.set(keyArgs, 'byNaked', false); - - this.base(chart, type, index, keyArgs); - }) - .add(/** @lends Legend# */{ - _getOptionsDefinition: function(){ - return legend_optionsDef; - } - }); - - /* PRIVATE STUFF */ - function castSize(size){ - // Single size or sizeMax (a number or a string) - // should be interpreted as meaning the orthogonal length. - - if(!def.object.is(size)){ - var position = this.option('Position'); - size = new pvc.Size() - .setSize(size, { - singleProp: pvc.BasePanel.orthogonalLength[position] - }); - } - - return size; - } - - function castAlign(align){ - var position = this.option('Position'); - return pvc.parseAlign(position, align); - } - - /*global axis_optionsDef:true*/ - var legend_optionsDef = { - /* legendPosition */ - Position: { - resolve: '_resolveFull', - cast: pvc.parsePosition, - value: 'bottom' - }, - - /* legendSize, - * legend2Size - */ - Size: { - resolve: '_resolveFull', - cast: castSize - }, - - SizeMax: { - resolve: '_resolveFull', - cast: castSize - }, - - Align: { - resolve: '_resolveFull', - data: { - resolveDefault: function(optionInfo){ - // Default value of align depends on position - var position = this.option('Position'); - var align; - if(position !== 'top' && position !== 'bottom'){ - align = 'top'; - } else if(this.chart.compatVersion() <= 1) { // centered is better - align = 'left'; - } - - optionInfo.defaultValue(align); - return true; - } - }, - cast: castAlign - }, - - Margins: { - resolve: '_resolveFull', - data: { - resolveDefault: function(optionInfo){ - // Default value of align depends on position - // Default value of margins depends on position - if(this.chart.compatVersion() > 1){ - var position = this.option('Position'); - - // Set default margins - var margins = def.set({}, pvc.BasePanel.oppositeAnchor[position], 5); - - optionInfo.defaultValue(margins); - } - - return true; - } - }, - cast: pvc.Sides.as - }, - - Paddings: { - resolve: '_resolveFull', - cast: pvc.Sides.as, - value: 5 - }, - - Font: { - resolve: '_resolveFull', - cast: String, - value: '10px sans-serif' - } - }; -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/OptionsBase.js b/pacotes/ccc2/pvc/visual/OptionsBase.js deleted file mode 100755 index 9540b8a..0000000 --- a/pacotes/ccc2/pvc/visual/OptionsBase.js +++ /dev/null @@ -1,168 +0,0 @@ - -/** - * Initializes a chart object with options. - * - * @name pvc.visual.OptionsBase - * - * @class Represents a chart object that has options. - * - * @property {pvc.BaseChart} chart The associated chart. - * @property {string} type The type of object. - * @property {number} index The index of the object within its type (0, 1, 2...). - * @property {string} [name] The name of the object. - * - * @constructor - * @param {pvc.BaseChart} chart The associated chart. - * @param {string} type The type of the object. - * @param {number} [index=0] The index of the object within its type. - * @param {object} [keyArgs] Keyword arguments. - * @param {string} [keyArgs.name] The name of the object. - */ -def -.type('pvc.visual.OptionsBase') -.init(function(chart, type, index, keyArgs){ - this.chart = chart; - this.type = type; - this.index = index == null ? 0 : index; - this.name = def.get(keyArgs, 'name'); - this.id = this._buildId(); - this.optionId = this._buildOptionId(); - - var rs = this._resolvers = []; - - this._registerResolversFull(rs, keyArgs); - - this.option = pvc.options(this._getOptionsDefinition(), this); -}) -.add(/** @lends pvc.visual.OptionsBase# */{ - - _buildId: function(){ - return pvc.buildIndexedId(this.type, this.index); - }, - - _buildOptionId: function(){ - return this.id; - }, - - _getOptionsDefinition: def.method({isAbstract: true}), - - _chartOption: function(name) { - return this.chart.options[name]; - }, - - _registerResolversFull: function(rs, keyArgs){ - // I - By Fixed values - var fixed = def.get(keyArgs, 'fixed'); - if(fixed){ - this._fixed = fixed; - rs.push( - pvc.options.specify(function(optionInfo){ - return fixed[optionInfo.name]; - })); - } - - this._registerResolversNormal(rs, keyArgs); - - // VI - By Default Values - var defaults = def.get(keyArgs, 'defaults'); - if(defaults){ - this._defaults = defaults; - } - - rs.push(this._resolveDefault); - }, - - _registerResolversNormal: function(rs, keyArgs){ - // II - By V1 Only Logic - if(this.chart.compatVersion() <= 1){ - rs.push(this._resolveByV1OnlyLogic); - } - - // III - By Name (ex: plot2, trend) - if(this.name){ - rs.push( - pvc.options.specify(function(optionInfo){ - return this._chartOption(this.name + def.firstUpperCase(optionInfo.name)); - })); - } - - // IV - By OptionId - rs.push(this._resolveByOptionId); - - // V - By Naked Id - if(def.get(keyArgs, 'byNaked', !this.index)){ - rs.push(this._resolveByNaked); - } - }, - - // ------------- - - _resolveFull: function(optionInfo){ - var rs = this._resolvers; - for(var i = 0, L = rs.length ; i < L ; i++){ - if(rs[i].call(this, optionInfo)){ - return true; - } - } - return false; - }, - - _resolveFixed: pvc.options.specify(function(optionInfo){ - if(this._fixed){ - return this._fixed[optionInfo.name]; - } - }), - - _resolveByV1OnlyLogic: function(optionInfo){ - var data = optionInfo.data; - var resolverV1; - if(data && (resolverV1 = data.resolveV1)){ - return resolverV1.call(this, optionInfo); - } - }, - - _resolveByName: pvc.options.specify(function(optionInfo){ - if(this.name){ - return this._chartOption(this.name + def.firstUpperCase(optionInfo.name)); - } - }), - - _resolveByOptionId: pvc.options.specify(function(optionInfo){ - return this._chartOption(this.optionId + def.firstUpperCase(optionInfo.name)); - }), - - _resolveByNaked: pvc.options.specify(function(optionInfo){ - // The first of the type receives options without any prefix. - if(!this.index){ - return this._chartOption(def.firstLowerCase(optionInfo.name)); - } - }), - - _resolveDefault: function(optionInfo){ - // Dynamic default value? - var data = optionInfo.data; - var resolverDefault; - if(data && (resolverDefault = data.resolveDefault)){ - if(resolverDefault.call(this, optionInfo)){ - return true; - } - } - - if(this._defaults){ - var value = this._defaults[optionInfo.name]; - if(value !== undefined){ - optionInfo.defaultValue(value); - return true; - } - } - }, - - _specifyChartOption: function(optionInfo, asName){ - var value = this._chartOption(asName); - if(value != null){ - optionInfo.specify(value); - return true; - } - } -}); - diff --git a/pacotes/ccc2/pvc/visual/Role.js b/pacotes/ccc2/pvc/visual/Role.js deleted file mode 100755 index bacc25a..0000000 --- a/pacotes/ccc2/pvc/visual/Role.js +++ /dev/null @@ -1,370 +0,0 @@ - -/** - * Initializes a visual role. - * - * @name pvc.visual.Role - * - * @class Represents a role that is somehow played by a visualization. - * - * @property {string} name The name of the role. - * - * @property {string} label - * The label of this role. - * The label should be unique on a visualization. - * - * @property {pvc.data.GroupingSpec} grouping The grouping specification currently bound to the visual role. - * - * @property {boolean} isRequired Indicates that the role is required and must be satisfied. - * - * @property {boolean} requireSingleDimension Indicates that the role can only be satisfied by a single dimension. - * A {@link pvc.visual.Role} of this type must have an associated {@link pvc.data.GroupingSpec} - * that has {@link pvc.data.GroupingSpec#isSingleDimension} equal to true. - * - * @property {boolean} valueType When not nully, - * restricts the allowed value type of the single dimension of the - * associated {@link pvc.data.GroupingSpec} to this type. - * - * @property {boolean|null} requireIsDiscrete - * Indicates if - * only discrete, when true, - * continuous, when false, - * or any, when null, - * groupings are accepted. - * - * @property {string} defaultDimensionName The default dimension name. - * - * @property {boolean} autoCreateDimension Indicates if a dimension with the default name (the first level of, when a group name), - * should be created when the role has not been read by a translator (required or not). - * - * @constructor - * @param {string} name The name of the role. - * @param {object} [keyArgs] Keyword arguments. - * @param {string} [keyArgs.label] The label of this role. - * - * @param {boolean} [keyArgs.isRequired=false] Indicates a required role. - * - * @param {boolean} [keyArgs.requireSingleDimension=false] Indicates that the role - * can only be satisfied by a single dimension. - * - * @param {boolean} [keyArgs.isMeasure=false] Indicates that datums that do not - * contain a non-null atom in any of the dimensions bound to measure roles should be readily excluded. - * - * @param {boolean} [keyArgs.valueType] Restricts the allowed value type of dimensions. - * - * @param {boolean|null} [keyArgs.requireIsDiscrete=null] Indicates if the grouping should be discrete, continuous or any. - * - * @param {string} [keyArgs.defaultDimensionName] The default dimension name. - * @param {boolean} [keyArgs.autoCreateDimension=false] - * Indicates if a dimension with the default name (the first level of, when a group name), - * should be created when the role is required and it has not been read by a translator. - * - * @param {string} [keyArgs.flatteningMode='singleLevel'] Indicates if the role presents - * the leaf data nodes or all the nodes in the tree, in pre or post order. - * Possible values are 'singleLevel', 'tree-pre' and 'tree-post'. - */ -def.type('pvc.visual.Role') -.init(function(name, keyArgs){ - this.name = name; - this.label = def.get(keyArgs, 'label') || pvc.buildTitleFromName(name); - this.index = def.get(keyArgs, 'index') || 0; - - this.dimensionDefaults = def.get(keyArgs, 'dimensionDefaults') || {}; - - if(def.get(keyArgs, 'isRequired', false)) { - this.isRequired = true; - } - - if(def.get(keyArgs, 'autoCreateDimension', false)) { - this.autoCreateDimension = true; - } - - var defaultSourceRoleName = def.get(keyArgs, 'defaultSourceRole'); - if(defaultSourceRoleName) { - this.defaultSourceRoleName = defaultSourceRoleName; - } - - var defaultDimensionName = def.get(keyArgs, 'defaultDimension'); - if(defaultDimensionName) { - this.defaultDimensionName = defaultDimensionName; - } - - if(!defaultDimensionName && this.autoCreateDimension){ - throw def.error.argumentRequired('defaultDimension'); - } - - var requireSingleDimension; - var requireIsDiscrete = def.get(keyArgs, 'requireIsDiscrete'); // isSingleDiscrete - if(requireIsDiscrete != null) { - if(!requireIsDiscrete) { - requireSingleDimension = true; - } - } - - if(requireSingleDimension != null) { - requireSingleDimension = def.get(keyArgs, 'requireSingleDimension', false); - if(requireSingleDimension) { - if(def.get(keyArgs, 'isMeasure', false)) { - this.isMeasure = true; - - if(def.get(keyArgs, 'isPercent', false)) { - this.isPercent = true; - } - } - - var valueType = def.get(keyArgs, 'valueType', null); - if(valueType !== this.valueType) { - this.valueType = valueType; - this.dimensionDefaults.valueType = valueType; - } - } - } - - if(requireSingleDimension !== this.requireSingleDimension) { - this.requireSingleDimension = requireSingleDimension; - } - - if(requireIsDiscrete != this.requireIsDiscrete) { - this.requireIsDiscrete = !!requireIsDiscrete; - this.dimensionDefaults.isDiscrete = this.requireIsDiscrete; - } - - var flatteningMode = def.get(keyArgs, 'flatteningMode'); - if(flatteningMode && flatteningMode != this.flatteningMode) { - this.flatteningMode = flatteningMode; - } -}) -.add(/** @lends pvc.visual.Role# */{ - isRequired: false, - requireSingleDimension: false, - valueType: null, - requireIsDiscrete: null, - isMeasure: false, - isPercent: false, - defaultSourceRoleName: null, - defaultDimensionName: null, - grouping: null, - flatteningMode: 'singleLevel', - flattenRootLabel: '', - autoCreateDimension: false, - isReversed: false, - label: null, - sourceRole: null, - - /** - * Obtains the first dimension type that is bound to the role. - * @type pvc.data.DimensionType - */ - firstDimensionType: function(){ - var g = this.grouping; - return g && g.firstDimensionType(); - }, - - /** - * Obtains the name of the first dimension type that is bound to the role. - * @type string - */ - firstDimensionName: function(){ - var g = this.grouping; - return g && g.firstDimensionName(); - }, - - /** - * Obtains the value type of the first dimension type that is bound to the role. - * @type function - */ - firstDimensionValueType: function(){ - var g = this.grouping; - return g && g.firstDimensionValueType(); - }, - - isDiscrete: function(){ - var g = this.grouping; - return g && g.isDiscrete(); - }, - - setSourceRole: function(sourceRole){ - this.sourceRole = sourceRole; - }, - - setIsReversed: function(isReversed){ - if(!isReversed){ // default value - delete this.isReversed; - } else { - this.isReversed = true; - } - }, - - setFlatteningMode: function(flatteningMode){ - if(!flatteningMode || flatteningMode === 'singleLevel'){ // default value - delete this.flatteningMode; - } else { - this.flatteningMode = flatteningMode; - } - }, - - setFlattenRootLabel: function(flattenRootLabel){ - if(!flattenRootLabel){ // default value - delete this.flattenRootLabel; - } else { - this.flattenRootLabel = flattenRootLabel; - } - }, - - /** - * Applies this role's grouping to the specified data - * after ensuring the grouping is of a certain type. - * - * @param {pvc.data.Data} data The data on which to apply the operation. - * @param {object} [keyArgs] Keyword arguments. - * ... - * - * @type pvc.data.Data - */ - flatten: function(data, keyArgs){ - if(this.grouping){ - return data.flattenBy(this, keyArgs); - } - }, - - flattenedGrouping: function(keyArgs){ - var grouping = this.grouping; - if(grouping){ - keyArgs = def.setDefaults(keyArgs, - 'flatteningMode', this.flatteningMode, - 'flattenRootLabel', this.flattenRootLabel); - - return grouping.ensure(keyArgs); - } - }, - - select: function(data, keyArgs){ - var grouping = this.grouping; - if(grouping){ - return data.groupBy(grouping.ensure(keyArgs), keyArgs); - } - }, - - view: function(complex){ - var grouping = this.grouping; - if(grouping){ - return grouping.view(complex); - } - }, - - /** - * Pre-binds a grouping specification to playing this role. - * - * @param {pvc.data.GroupingSpec} groupingSpec The grouping specification of the visual role. - */ - preBind: function(groupingSpec){ - this.__grouping = groupingSpec; - - return this; - }, - - isPreBound: function(){ - return !!this.__grouping; - }, - - preBoundGrouping: function(){ - return this.__grouping; - }, - - isBound: function(){ - return !!this.grouping; - }, - - /** - * Finalizes a binding initiated with {@link #preBind}. - * - * @param {pvc.data.ComplexType} type The complex type with which - * to bind the pre-bound grouping and then validate the - * grouping and role binding. - */ - postBind: function(type){ - var grouping = this.__grouping; - if(grouping){ - delete this.__grouping; - - grouping.bind(type); - - this.bind(grouping); - } - - return this; - }, - - /** - * Binds a grouping specification to playing this role. - * - * @param {pvc.data.GroupingSpec} groupingSpec The grouping specification of the visual role. - */ - bind: function(groupingSpec){ - if(groupingSpec) { - if(groupingSpec.isNull()){ - groupingSpec = null; - } else { - /* Validate grouping spec according to role */ - - if(this.requireSingleDimension && !groupingSpec.isSingleDimension) { - throw def.error.operationInvalid( - "Role '{0}' only accepts a single dimension.", - [this.name]); - } - - var valueType = this.valueType; - var requireIsDiscrete = this.requireIsDiscrete; - groupingSpec.dimensions().each(function(dimSpec){ - var dimType = dimSpec.type; - if(valueType && dimType.valueType !== valueType) { - throw def.error.operationInvalid( - "Role '{0}' cannot be bound to dimension '{1}'. \nIt only accepts dimensions of type '{2}' and not of type '{3}'.", - [this.name, dimType.name, pvc.data.DimensionType.valueTypeName(valueType), dimType.valueTypeName]); - } - - if(requireIsDiscrete != null && - dimType.isDiscrete !== requireIsDiscrete) { - - if(requireIsDiscrete){ - // A continuous dimension can be "coerced" to behave as discrete - dimType._toDiscrete(); - } else { - throw def.error.operationInvalid( - "Role '{0}' cannot be bound to dimension '{1}'. \nIt only accepts {2} dimensions.", - [this.name, dimType.name, requireIsDiscrete ? 'discrete' : 'continuous']); - } - } - }, this); - } - } - - // ---------- - - if(this.grouping) { - // unregister from current dimension types - this.grouping.dimensions().each(function(dimSpec){ - if(dimSpec.type){ - /*global dimType_removeVisualRole:true */ - dimType_removeVisualRole.call(dimSpec.type, this); - } - }, this); - } - - this.grouping = groupingSpec; - - if(this.grouping) { - - if(this.isReversed){ - this.grouping = this.grouping.reversed(); - } - - // register in current dimension types - this.grouping.dimensions().each(function(dimSpec){ - /*global dimType_addVisualRole:true */ - dimType_addVisualRole.call(dimSpec.type, this); - }, this); - } - - return this; - } -}); diff --git a/pacotes/ccc2/pvc/visual/Scene.js b/pacotes/ccc2/pvc/visual/Scene.js deleted file mode 100755 index 6a0075b..0000000 --- a/pacotes/ccc2/pvc/visual/Scene.js +++ /dev/null @@ -1,358 +0,0 @@ - -/** - * Initializes a scene. - * - * @name pvc.visual.Scene - * @class Scenes guide the rendering of protovis marks; - * they are supplied to {@link pv.Mark} data property. - *

- * A scene may feed several marks and so is not specific to a given mark - * (contrast with protovis' instances/scenes). - *

- *

- * Scenes provide a well defined interface to pvc's - * extension point functions. - *

- *

- * Scenes hold precomputed data, that does not change with interaction, - * and that is thus not recalculated in every protovis render caused by interaction. - *

- *

- * Scenes bridge the gap between data and visual roles. - * Data can be accessed by one or the other view. - *

- * - * @borrows pv.Dom.Node#visitBefore as #visitBefore - * @borrows pv.Dom.Node#visitAfter as #visitAfter - * - * @borrows pv.Dom.Node#nodes as #nodes - * @borrows pv.Dom.Node#firstChild as #firstChild - * @borrows pv.Dom.Node#lastChild as #lastChild - * @borrows pv.Dom.Node#previousSibling as #previousSibling - * @borrows pv.Dom.Node#nextSibling as #nextSibling - * - * - * @property {pvc.data.Data} group The data group that's present in the scene, or null, if none. - * @property {pvc.data.Datum} datum The datum that's present in the scene, or null, if none. - * @property {object} atoms The map of atoms, by dimension name, that's present in the scene, or null, if none. - *

- * When there is a group, these are its atoms, - * otherwise, - * if there is a datum, - * these are its atoms. - *

- *

- * Do NOT modify this object. - *

- * - * @constructor - * @param {pvc.visual.Scene} [parent=null] The parent scene. - * @param {object} [keyArgs] Keyword arguments. - * @property {pvc.data.Data} [keyArgs.group=null] The data group that's present in the scene. - * Specify only one of the arguments group or datum. - * @property {pvc.data.Datum} [keyArgs.datum=null] The single datum that's present in the scene. - * Specify only one of the arguments group or datum. - */ -def.type('pvc.visual.Scene') -.init(function(parent, keyArgs){ - if(pvc.debug >= 4){ - this.id = def.nextId('scene'); - } - - this._renderId = 0; - this.renderState = {}; - - pv.Dom.Node.call(this, /* nodeValue */null); - - this.parent = parent || null; - this.root = this; - if(parent){ - // parent -> ((pv.Dom.Node#)this).parentNode - // this -> ((pv.Dom.Node#)parent).childNodes - // ... - var index = def.get(keyArgs, 'index', null); - parent.insertAt(this, index); - this.root = parent.root; - } else { - /* root scene */ - this._active = null; - this._panel = def.get(keyArgs, 'panel') || - def.fail.argumentRequired('panel', "Argument is required on root scene."); - } - - /* DATA */ - var group = def.get(keyArgs, 'group', null), - datum; - if(group){ - datum = group._datums[0]; // null on empty datas (just try hiding all series with the legend) - } else { - datum = def.get(keyArgs, 'datum'); - } - - this.datum = datum || null; - this.group = group; - - var parentAtoms; - var source = (group || datum); - this.atoms = source ? source.atoms : - (parentAtoms = (parent && parent.atoms)) ? Object.create(parentAtoms) : - {}; - - source = (datum || group); - this.firstAtoms = source ? source.atoms : - (parentAtoms = (parent && parent.firstAtoms)) ? Object.create(parentAtoms) : - this.atoms; - - if(!source){ - // This logic can be changed (see PointPanel) - this.isNull = true; - } - - /* VARS */ - this.vars = parent ? Object.create(parent.vars) : {}; -}) -.add(pv.Dom.Node) - -.add(/** @lends pvc.visual.Scene# */{ - isNull: false, - - /** - * Obtains an enumerable of the datums present in the scene. - * - * @type def.Query - */ - datums: function(){ - return this.group ? - this.group.datums() : - (this.datum ? def.query(this.datum) : def.query()); - }, - - /* - * {value} -> <=> this.vars.value.label - * {value.value} -> <=> this.vars.value.value - * {#sales} -> <=> this.atoms.sales.label - */ - format: function(mask){ - return def.format(mask, this._formatScope, this); - }, - - _formatScope: function(prop){ - if(prop.charAt(0) === '#'){ - // An atom name - prop = prop.substr(1).split('.'); - if(prop.length > 2){ - throw def.error.operationInvalid("Scene format mask is invalid."); - } - - var atom = this.atoms[prop[0]]; - if(atom){ - if(prop.length > 1) { - switch(prop[1]){ - case 'value': return atom.value; - case 'label': break; - default: throw def.error.operationInvalid("Scene format mask is invalid."); - } - } - - // atom.toString() ends up returning atom.label - return atom; - } - - return null; // Atom does not exist --> "" - } - - // A scene var name - return def.getPath(this.vars, prop); // Scene vars' toString may end up being called - }, - - isRoot: function(){ - return this.root === this; - }, - - panel: function(){ - return this.root._panel; - }, - - chart: function(){ - return this.root._panel.chart; - }, - - compatVersion: function(){ - return this.root._panel.compatVersion(); - }, - - /** - * Obtains an enumerable of the child scenes. - * - * @type def.Query - */ - children: function(){ - if(!this.childNodes) { - return def.query(); - } - - return def.query(this.childNodes); - }, - - leafs: function(){ - function getFirstLeafFrom(leaf){ - // Find first leaf from current - while(leaf.childNodes.length){ - leaf = leaf.childNodes[0]; - } - - return leaf; - } - - var root = this; - return def.query(function(nextIndex){ - if(!nextIndex){ - // Initialize - var item = getFirstLeafFrom(root); - if(item === root){ - return 0; - } - - this.item = item; - return 1; // has next - } - - // Has a next sibling? - var next = this.item.nextSibling; - if(next){ - this.item = next; - return 1; // has next - } - - // Go to closest ancestor that has a sibling - var current = this.item; - while((current !== root) && (current = current.parentNode)){ - if((next = current.nextSibling)){ - // Take the first leaf from there - this.item = getFirstLeafFrom(next); - return 1; - } - } - - return 0; - }); - }, - - /* INTERACTION */ - anyInteraction: function(){ - return (!!this.root._active || this.anySelected()); - }, - - /* ACTIVITY */ - isActive: false, - - setActive: function(isActive){ - isActive = !!isActive; // normalize - if(this.isActive !== isActive){ - rootScene_setActive.call(this.root, this.isActive ? null : this); - } - }, - - clearActive: function(){ - return rootScene_setActive.call(this.root, null); - }, - - anyActive: function(){ - return !!this.root._active; - }, - - active: function(){ - return this.root._active; - }, - - activeSeries: function(){ - var active = this.active(); - var seriesVar; - return active && (seriesVar = active.vars.series) && seriesVar.value; - }, - - isActiveSeries: function(){ - if(this.isActive){ - return true; - } - - var activeSeries; - return (activeSeries = this.activeSeries()) != null && - (activeSeries === this.vars.series.value); - }, - - /* SELECTION */ - isSelected: function(){ - return this._selectedData().is; - }, - - anySelected: function(){ - return this._selectedData().any; - }, - - _selectedData: function(){ - return this.renderState._selectedData || - (this.renderState._selectedData = this._createSelectedData()); - }, - - _createSelectedData: function(){ - var any = this.panel().chart.data.owner.selectedCount() > 0, - isSelected = any && - this.datums() - .any(function(datum){ return datum.isSelected; }); - - return { - any: any, - is: isSelected - }; - } -}); - -/** - * Called on each sign's pvc.visual.Sign#buildInstance - * to ensure cached data per-render is cleared. - * - * @param {number} renderId The current render id. - */ -function scene_renderId(renderId){ - if(this._renderId !== renderId){ - if(pvc.debug >= 20){ - pvc.log({sceneId: this.id, oldRenderId: this._renderId, newRenderId: renderId}); - } - - this._renderId = renderId; - this.renderState = {}; - } -} - -function rootScene_setActive(scene){ - var ownerScene; - if(scene && (ownerScene = scene.ownerScene)){ - scene = ownerScene; - } - - if(this._active !== scene){ - if(this._active){ - scene_setActive.call(this._active, false); - } - - this._active = scene || null; - - if(this._active){ - scene_setActive.call(this._active, true); - } - return true; - } - return false; -} - -function scene_setActive(isActive){ - isActive = !!isActive; // normalize - if(this.isActive !== isActive){ - if(!isActive){ - delete this.isActive; - } else { - this.isActive = true; - } - } -} \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/SizeAxis.js b/pacotes/ccc2/pvc/visual/SizeAxis.js deleted file mode 100755 index 01be52a..0000000 --- a/pacotes/ccc2/pvc/visual/SizeAxis.js +++ /dev/null @@ -1,81 +0,0 @@ -var sizeAxis_optionsDef; - -def.scope(function(){ - /** - * Initializes a size axis. - * - * @name pvc.visual.SizeAxis - * - * @class Represents an axis that maps sizes to the values of a role. - * - * @extends pvc.visual.Axis - */ - def - .type('pvc.visual.SizeAxis', pvc.visual.Axis) - .init(function(chart, type, index, keyArgs){ - - // prevent naked resolution of size axis - keyArgs = def.set(keyArgs, 'byNaked', false); - - this.base(chart, type, index, keyArgs); - }) - .add(/** @lends pvc.visual.SizeAxis# */{ - - scaleTreatsNullAs: function(){ - return 'min'; - }, - - scaleUsesAbs: function(){ - return this.option('UseAbs'); - }, - - setScaleRange: function(range){ - var scale = this.scale; - scale.min = range.min; - scale.max = range.max; - scale.size = range.max - range.min; - - scale.range(scale.min, scale.max); - - if(pvc.debug >= 4){ - pvc.log("Scale: " + pvc.stringify(def.copyOwn(scale))); - } - - return this; - }, - - _getOptionsDefinition: function(){ - return sizeAxis_optionsDef; - } - }); - - /*global axis_optionsDef:true */ - sizeAxis_optionsDef = def.create(axis_optionsDef, { - /* sizeAxisOriginIsZero - * Force zero to be part of the domain of the scale to make - * the scale "proportionally" comparable. - */ - OriginIsZero: { - resolve: '_resolveFull', - cast: Boolean, - value: false - }, - - FixedMin: { - resolve: '_resolveFull', - cast: pvc.castNumber - }, - - FixedMax: { - resolve: '_resolveFull', - cast: pvc.castNumber - }, - - UseAbs: { - resolve: '_resolveFull', - cast: Boolean, - value: false - } - }); - -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/Var.js b/pacotes/ccc2/pvc/visual/Var.js deleted file mode 100755 index 341e604..0000000 --- a/pacotes/ccc2/pvc/visual/Var.js +++ /dev/null @@ -1,147 +0,0 @@ - -/** - * Initializes a scene variable. - * - * @name pvc.visual.ValueLabelVar - * @class A scene variable holds the concrete value that - * a {@link pvc.visual.Role} or other relevant piece of information - * has in a {@link pvc.visual.Scene}. - * Usually, it also contains a label that describes it. - * - * @constructor - * @param {any} value The value of the variable. - * @param {any} label The label of the variable. - * @param {any} [rawValue] The raw value of the variable. - */ -pvc.visual.ValueLabelVar = function(value, label, rawValue){ - this.value = value; - this.label = label; - - if(rawValue !== undefined){ - this.rawValue = rawValue; - } -}; - -def.set( - pvc.visual.ValueLabelVar.prototype, - 'rawValue', undefined, - 'clone', function(){ - return new pvc.visual.ValueLabelVar(this.value, this.label, this.rawValue); - }, - 'toString', function(){ - var label = this.label || this.value; - return typeof label !== 'string' ? ('' + label) : label; - }); - -pvc.visual.ValueLabelVar.fromComplex = function(complex){ - return complex ? - new pvc.visual.ValueLabelVar(complex.value, complex.label, complex.rawValue) : - new pvc.visual.ValueLabelVar(null, "", null) - ; -}; - -def -.type('pvc.visual.RoleVarHelper') -.init(function(rootScene, role, keyArgs){ - var g; - var hasPercentSubVar = def.get(keyArgs, 'hasPercentSubVar', false); - - if(!def.get(keyArgs, 'forceUnbound', false)){ - this.role = role; - this.sourceRoleName = role.sourceRole && role.sourceRole.name; - - g = this.grouping = role.grouping; - if(g && !g.isDiscrete()){ - var panel = rootScene.panel(); - this.rootContDim = panel.data.owner.dimensions(g.firstDimensionName()); - if(hasPercentSubVar){ - this.percentFormatter = panel.chart.options.percentValueFormat; - } - } - } - - if(!g){ - // Unbound role - // Simply place a null variable in the root scene - var roleVar = rootScene.vars[role.name] = new pvc.visual.ValueLabelVar(null, ""); - if(hasPercentSubVar){ - roleVar.percent = new pvc.visual.ValueLabelVar(null, ""); - } - } -}) -.add({ - isBound: function(){ - return !!this.grouping; - }, - - onNewScene: function(scene, isLeaf){ - if(!this.grouping){ - return; - } - - var roleName = this.role.name; - if(scene.vars[roleName]){ - return; - } - - var sourceName = this.sourceRoleName; - if(sourceName){ - var sourceVar = def.getOwn(scene.vars, sourceName); - if(sourceVar){ - scene.vars[roleName] = sourceVar.clone(); - return; - } - } - - if(isLeaf){ - // Not grouped, so there's no guarantee that - // there's a single value for all the datums of the group. - - var roleVar; - var rootContDim = this.rootContDim; - if(!rootContDim){ - // Discrete - - // We choose the value of the first datum of the group... - var firstDatum = scene.datum; - if(firstDatum && !firstDatum.isNull){ - var view = this.grouping.view(firstDatum); - roleVar = new pvc.visual.ValueLabelVar( - view.value, - view.label, - view.rawValue); - } - } else { - var group = scene.group; - var singleDatum = group ? group.singleDatum() : scene.datum; - if(singleDatum){ - if(!singleDatum.isNull){ - // Simpy inherit from the atom, to save memory - // The Atom is compatible with the "Var" interface - roleVar = Object.create(singleDatum.atoms[rootContDim.name]); - } - } else if(group){ - var valueDim = group.dimensions(rootContDim.name); - var value = valueDim.sum({visible: true, zeroIfNone: false}); - var label = rootContDim.format(value); - - roleVar = new pvc.visual.ValueLabelVar(value, label, value); - if(this.percentFormatter){ - if(value == null){ - roleVar.percent = new pvc.visual.ValueLabelVar(value, label); - } else { - var valuePct = valueDim.percentOverParent({visible: true}); - - roleVar.percent = new pvc.visual.ValueLabelVar( - valuePct, - this.percentFormatter.call(null, valuePct)); - } - } - } - } - - scene.vars[roleName] = roleVar || - new pvc.visual.ValueLabelVar(null, ""); - } - } -}); diff --git a/pacotes/ccc2/pvc/visual/legend/BulletGroupScene.js b/pacotes/ccc2/pvc/visual/legend/BulletGroupScene.js deleted file mode 100755 index d0f3cf2..0000000 --- a/pacotes/ccc2/pvc/visual/legend/BulletGroupScene.js +++ /dev/null @@ -1,90 +0,0 @@ - -/** - * Initializes a legend bullet group scene. - * - * @name pvc.visual.legend.BulletGroupScene - - * @extends pvc.visual.Scene - * - * @constructor - * @param {pvc.visual.legend.BulletRootScene} parent The parent bullet root scene. - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.visual.Scene} for additional keyword arguments. - * @param {pv.visual.legend.renderer} [keyArgs.renderer] Keyword arguments. - */ -def -.type('pvc.visual.legend.BulletGroupScene', pvc.visual.Scene) -.init(function(rootScene, keyArgs){ - - this.base(rootScene, keyArgs); - - this.extensionPrefix = def.get(keyArgs, 'extensionPrefix') || ''; - this._renderer = def.get(keyArgs, 'renderer'); - - this.colorAxis = def.get(keyArgs, 'colorAxis'); - this.clickMode = def.get(keyArgs, 'clickMode'); - - if(this.colorAxis && !this.clickMode){ - this.clickMode = this.colorAxis.option('LegendClickMode'); - } -}) -.add(/** @lends pvc.visual.legend.BulletGroupScene# */{ - hasRenderer: function(){ - return this._renderer; - }, - - renderer: function(renderer){ - if(renderer != null){ - this._renderer = renderer; - } else { - renderer = this._renderer; - if(!renderer){ - var keyArgs; - var colorAxis = this.colorAxis; - if(colorAxis){ - keyArgs = { - drawRule: colorAxis.option('LegendDrawLine' ), - drawMarker: colorAxis.option('LegendDrawMarker'), - markerShape: colorAxis.option('LegendShape') - }; - } - - renderer = new pvc.visual.legend.BulletItemDefaultRenderer(keyArgs); - this._renderer = renderer; - } - } - - return renderer; - }, - - itemSceneType: function(){ - var ItemType = this._itemSceneType; - if(!ItemType){ - ItemType = def.type(pvc.visual.legend.BulletItemScene); - - // Mixin behavior depending on click mode - var clickMode = this.clickMode; - switch(clickMode){ - case 'toggleSelected': - ItemType.add(pvc.visual.legend.BulletItemSceneSelection); - break; - - case 'toggleVisible': - ItemType.add(pvc.visual.legend.BulletItemSceneVisibility); - break; - } - - // Apply legend item scene extensions - this.panel()._extendSceneType('item', ItemType, ['isOn', 'isClickable', 'click']); - - this._itemSceneType = ItemType; - } - - return ItemType; - }, - - createItem: function(keyArgs){ - var ItemType = this.itemSceneType(); - return new ItemType(this, keyArgs); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/legend/BulletItemDefaultRenderer.js b/pacotes/ccc2/pvc/visual/legend/BulletItemDefaultRenderer.js deleted file mode 100755 index 584988d..0000000 --- a/pacotes/ccc2/pvc/visual/legend/BulletItemDefaultRenderer.js +++ /dev/null @@ -1,124 +0,0 @@ - -/** - * Initializes a default legend bullet renderer. - * - * @name pvc.visual.legend.BulletItemDefaultRenderer - * @class The default bullet renderer. - * @extends pvc.visual.legend.BulletItemRenderer - * - * @constructor - * @param {pvc.visual.legend.BulletGroupScene} bulletGroup The parent legend bullet group scene. - * @param {object} [keyArgs] Optional keyword arguments. - * @param {string} [keyArgs.drawRule=false] Whether a rule should be drawn. - * @param {string} [keyArgs.drawMarker=true] Whether a marker should be drawn. - * When {@link keyArgs.drawRule} is false, then this argument is ignored, - * because a marker is necessarily drawn. - * @param {pv.Mark} [keyArgs.markerPvProto] The marker's protovis prototype mark. - * @param {pv.Mark} [keyArgs.rulePvProto ] The rule's protovis prototype mark. - */ -def -.type('pvc.visual.legend.BulletItemDefaultRenderer', pvc.visual.legend.BulletItemRenderer) -.init(function(keyArgs){ - this.noSelect = def.get(keyArgs, 'noSelect', false); - this.noHover = def.get(keyArgs, 'noHover', false); - - this.drawRule = def.get(keyArgs, 'drawRule', false); - if(this.drawRule){ - this.rulePvProto = def.get(keyArgs, 'rulePvProto'); - } - - this.drawMarker = !this.drawRule || def.get(keyArgs, 'drawMarker', true); - if(this.drawMarker){ - this.markerShape = def.get(keyArgs, 'markerShape', 'square'); - this.markerPvProto = def.get(keyArgs, 'markerPvProto'); - } -}) -.add(/** @lends pvc.visual.legend.BulletItemDefaultRenderer# */{ - drawRule: false, - drawMarker: true, - markerShape: null, - rulePvProto: null, - markerPvProto: null, - - create: function(legendPanel, pvBulletPanel, extensionPrefix, wrapper){ - var renderInfo = {}; - var drawRule = this.drawRule; - var sceneColorProp = function(scene){ - return scene.color; - }; - - if(drawRule){ - var rulePvBaseProto = new pv.Mark() - .left (0) - .top (function(){ return this.parent.height() / 2; }) - .width(function(){ return this.parent.width(); }) - .lineWidth(1, pvc.extensionTag) // act as if it were a user extension - .strokeStyle(sceneColorProp, pvc.extensionTag) // idem - ; - - if(this.rulePvProto){ - rulePvBaseProto = this.rulePvProto.extend(rulePvBaseProto); - } - - renderInfo.pvRule = new pvc.visual.Rule(legendPanel, pvBulletPanel, { - proto: rulePvBaseProto, - noSelect: this.noSelect, - noHover: this.noHover, - activeSeriesAware: false,// no guarantee that series exist in the scene - extensionId: extensionPrefix + "Rule", - wrapper: wrapper - }) - .pvMark; - } - - if(this.drawMarker){ - var markerPvBaseProto = new pv.Mark() - // Center the marker in the panel - .left(function(){ - return this.parent.width () / 2; - }) - .top (function(){ - return this.parent.height() / 2; - }) - // If order of properties is changed, by extension, - // dependent properties will not work... - .shapeSize(function(){ return this.parent.width(); }, pvc.extensionTag) // width <= height - .lineWidth(2, pvc.extensionTag) - .fillStyle(sceneColorProp, pvc.extensionTag) - .strokeStyle(sceneColorProp, pvc.extensionTag) - .shape(this.markerShape, pvc.extensionTag) - .angle(drawRule ? 0 : Math.PI/2, pvc.extensionTag) // So that 'bar' gets drawn vertically - .antialias( function(){ - var cos = Math.abs(Math.cos(this.angle())); - if(cos !== 0 && cos !== 1){ - switch(this.shape()){ - case 'square': - case 'bar': - return false; - } - } - - return true; - }, pvc.extensionTag) - ; - - if(this.markerPvProto){ - markerPvBaseProto = this.markerPvProto.extend(markerPvBaseProto); - } - - renderInfo.pvDot = new pvc.visual.Dot(legendPanel, pvBulletPanel, { - proto: markerPvBaseProto, - freePosition: true, - activeSeriesAware: false, // no guarantee that series exist in the scene - noTooltip: true, - noSelect: this.noSelect, - noHover: this.noHover, - extensionId: extensionPrefix + "Dot", - wrapper: wrapper - }) - .pvMark; - } - - return renderInfo; - } -}); diff --git a/pacotes/ccc2/pvc/visual/legend/BulletItemRenderer.js b/pacotes/ccc2/pvc/visual/legend/BulletItemRenderer.js deleted file mode 100755 index c5dc4eb..0000000 --- a/pacotes/ccc2/pvc/visual/legend/BulletItemRenderer.js +++ /dev/null @@ -1,29 +0,0 @@ - -/** - * @name pvc.visual.legend.BulletItemRenderer - * @class Renders bullet items' bullets, i.e. marker, rule, etc. - */ -def.type('pvc.visual.legend.BulletItemRenderer'); - -/** - * Creates the marks that render appropriate bullets - * as children of a given parent bullet panel. - *

- * The dimensions of this panel, upon each render, - * provide bounds for drawing each bullet. - *

- *

- * The properties of marks created as children of this panel will - * receive a corresponding {@link pvc.visual.legend.BulletItemScene} - * as first argument. - *

- * - * @name pvc.visual.legend.BulletItemRenderer#create - * @function - * @param {pvc.LegendPanel} legendPanel the legend panel - * @param {pv.Panel} pvBulletPanel the protovis panel on which bullets are rendered. - * @param {string} extensionPrefix The extension prefix to be used to build extension keys, without underscore. - * @param {function} [wrapper] extension wrapper function to apply to created marks. - * - * @type undefined - */ \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/legend/BulletItemScene.js b/pacotes/ccc2/pvc/visual/legend/BulletItemScene.js deleted file mode 100755 index e16d24d..0000000 --- a/pacotes/ccc2/pvc/visual/legend/BulletItemScene.js +++ /dev/null @@ -1,106 +0,0 @@ - -/** - * Initializes a legend bullet item scene. - * - * @name pvc.visual.legend.BulletItemScene - * - * @extends pvc.visual.legend.Scene - * - * @constructor - * @param {pvc.visual.legend.BulletGroupScene} bulletGroup The parent legend bullet group scene. - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.visual.Scene} for supported keyword arguments. - */ -def -.type('pvc.visual.legend.BulletItemScene', pvc.visual.Scene) -.init(function(bulletGroup, keyArgs){ - - this.base(bulletGroup, keyArgs); - - var value, rawValue, label; - if(keyArgs){ - value = keyArgs.value; - rawValue = keyArgs.rawValue; - label = keyArgs.label; - } - - if(value === undefined){ - var source = this.group || this.datum; - if(source){ - value = source.value; - rawValue = source.rawValue; - label = source.ensureLabel(); - - // This is to catch trend lines... - // Standard data source data parts are numbers, - // so this shows the non-standard data part label - // after the item's label: - // 'Lisbon (Linear trend)' - var dataPartDim = this.chart()._getDataPartDimName(); - if(dataPartDim){ - var dataPartAtom = source.atoms[dataPartDim]; - if(isNaN(+dataPartAtom.value)){ - label += " (" + dataPartAtom.label + ")"; - } - } - } - } - - this.vars.value = new pvc.visual.ValueLabelVar(value || null, label || "", rawValue); -}) -.add(/** @lends pvc.visual.legend.BulletItemScene# */{ - /** - * Called during legend render (full or interactive) - * to determine if the item is in the "on" state. - *

- * An item in the "off" state is shown with brighter struck-through text, by default. - *

- * - *

- * The default implementation returns true. - *

- * - * @type boolean - */ - isOn: function(){ - return true; - }, - - /** - * Called during legend render (full or interactive) - * to determine if the item can be clicked. - *

- * A clickable item shows a hand mouse cursor when the mouse is over it. - *

- *

- * The default implementation returns false. - *

- * - * @type boolean - */ - isClickable: function(){ - return false; - }, - - /** - * Called when the user clicks the legend item. - *

- * The default implementation does nothing. - *

- */ - click: function(){ - // NOOP - }, - - /** - * Measures the item label's text and returns an object - * with 'width' and 'height' properties, in pixels. - *

A nully value may be returned to indicate that there is no text.

- * - * @type object - */ - labelTextSize: function(){ - var valueVar = this.vars.value; - return valueVar && pv.Text.measure(valueVar.label, this.vars.font); - } -}); diff --git a/pacotes/ccc2/pvc/visual/legend/BulletItemSceneSelection.js b/pacotes/ccc2/pvc/visual/legend/BulletItemSceneSelection.js deleted file mode 100755 index 1bd7e37..0000000 --- a/pacotes/ccc2/pvc/visual/legend/BulletItemSceneSelection.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @name pvc.visual.legend.BulletItemSceneSelection - * @class A selection behavior mixin for the legend bullet item scene. - * Represents and controls the selected state of its datums. - * - * @extends pvc.visual.legend.BulletItemScene - */ -def -.type('pvc.visual.legend.BulletItemSceneSelection') -.add(/** @lends pvc.visual.legend.BulletItemSceneSelection# */{ - /** - * Returns true if there are no selected datums in the owner data, - * or if at least one non-null datum of the scene's {@link #datums} is selected. - * @type boolean - */ - isOn: function(){ - var owner = (this.group || this.datum).owner; - return !owner.selectedCount() || - this.datums().any(function(datum){ - return !datum.isNull && datum.isSelected; - }); - - // Cannot use #isSelected() cause it includes null datums. - //return this.isSelected(); - }, - - /** - * Returns true if the chart is selectable by clicking. - * @type boolean - */ - isClickable: function(){ - return this.chart()._canSelectWithClick(); - }, - - /** - * Toggles the selected state of the datums present in this scene - * and updates the chart if necessary. - */ - click: function(){ - var datums = this.datums().array(); - if(datums.length){ - var chart = this.chart(); - chart._updatingSelections(function(){ - datums = chart._onUserSelection(datums); - if(datums){ - var on = def.query(datums).any(function(datum){ return datum.isSelected; }); - pvc.data.Data.setSelected(datums, !on); - } - }); - } - } -}); diff --git a/pacotes/ccc2/pvc/visual/legend/BulletItemSceneVisibility.js b/pacotes/ccc2/pvc/visual/legend/BulletItemSceneVisibility.js deleted file mode 100755 index d48aee6..0000000 --- a/pacotes/ccc2/pvc/visual/legend/BulletItemSceneVisibility.js +++ /dev/null @@ -1,41 +0,0 @@ - -/** - * @name pvc.visual.legend.BulletItemSceneVisibility - * - * @class A visibility behavior mixin for a legend bullet item scene. - * Represents and controls the visible state of its datums. - * - * @extends pvc.visual.legend.BulletItemScene - */ -def -.type('pvc.visual.legend.BulletItemSceneVisibility') -.add(/** @lends pvc.visual.legend.BulletItemSceneVisibility# */{ - /** - * Returns true if at least one non-null datum of the scene's {@link #datums} is visible. - * @type boolean - */ - isOn: function(){ - return this.datums().any(function(datum){ - return !datum.isNull && datum.isVisible; - }); - }, - - /** - * Returns true. - * @type boolean - */ - isClickable: function(){ - return true; - }, - - /** - * Toggles the visible state of the datums present in this scene - * and forces a re-render of the chart (without reloading data). - */ - click: function(){ - if(pvc.data.Data.toggleVisible(this.datums())){ - // Re-render chart - this.chart().render(true, true, false); - } - } -}); diff --git a/pacotes/ccc2/pvc/visual/legend/BulletRootScene.js b/pacotes/ccc2/pvc/visual/legend/BulletRootScene.js deleted file mode 100755 index e68431e..0000000 --- a/pacotes/ccc2/pvc/visual/legend/BulletRootScene.js +++ /dev/null @@ -1,191 +0,0 @@ - -/** - * Initializes a legend bullet root scene. - * - * @name pvc.visual.legend.BulletRootScene - * - * @extends pvc.visual.Scene - * - * @constructor - * @param {pvc.visual.Scene} [parent] The parent scene, if any. - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.visual.Scene} for supported keyword arguments. - */ -def -.type('pvc.visual.legend.BulletRootScene', pvc.visual.Scene) -.init(function(parent, keyArgs){ - - this.base(parent, keyArgs); - - var markerDiam = def.get(keyArgs, 'markerSize', 15); - var itemPadding = new pvc.Sides(def.get(keyArgs, 'itemPadding', 5)) - .resolve(markerDiam, markerDiam); - def.set(this.vars, - 'horizontal', def.get(keyArgs, 'horizontal', false), - 'font', def.get(keyArgs, 'font'), - 'markerSize', markerDiam, // Diameter of bullet/marker zone - 'textMargin', def.get(keyArgs, 'textMargin', 6), // Space between marker and text - 'itemPadding', itemPadding); -}) -.add(/** @lends pvc.visual.legend.BulletRootScene# */{ - layout: function(layoutInfo){ - // Any size available? - var clientSize = layoutInfo.clientSize; - if(!(clientSize.width > 0 && clientSize.height > 0)){ - return new pvc.Size(0,0); - } - - var desiredClientSize = layoutInfo.desiredClientSize; - - // The size of the biggest cell - var markerDiam = this.vars.markerSize; - var textLeft = markerDiam + this.vars.textMargin; - var itemPadding = this.vars.itemPadding; - - // Names are for legend items when laid out in rows - var a_width = this.vars.horizontal ? 'width' : 'height'; - var a_height = pvc.BasePanel.oppositeLength[a_width]; // height or width - - var maxRowWidth = desiredClientSize[a_width]; - if(!maxRowWidth || maxRowWidth < 0){ - maxRowWidth = clientSize[a_width]; // row or col - } - - var row; - var rows = []; - var contentSize = {width: 0, height: 0}; - - this.childNodes.forEach(function(groupScene){ - groupScene.childNodes.forEach(layoutItem, this); - }, this); - - // If there's no pending row to commit, there are no rows... - // No items or just items with no text -> hide - if(!row){ - return new pvc.Size(0,0); - } - - commitRow(/* isLast */ true); - - // In logical "row" naming - def.set(this.vars, - 'rows', rows, - 'rowCount', row, - 'size', contentSize); - - var isV1Compat = this.compatVersion() <= 1; - - // Request used width / all available width (V1) - var w = isV1Compat ? maxRowWidth : contentSize.width; - var h = desiredClientSize[a_height]; - if(!h || h < 0){ - h = contentSize.height; - } - - // requestSize - return def.set({}, - a_width, Math.min(w, clientSize[a_width]), - a_height, Math.min(h, clientSize[a_height])); - - function layoutItem(itemScene){ - // The names of props of textSize and itemClientSize - // are to be taken literally. - // This is because items, themselves, are always laid out horizontally... - var textSize = itemScene.labelTextSize(); - - var hidden = !textSize || !textSize.width || !textSize.height; - itemScene.isHidden = hidden; - if(hidden){ - return; - } - - // Add small margin to the end of the text eq to 0.5em - var widthMargin = 0;// (textSize.height / 2); - - // not padded size - var itemClientSize = { - width: textLeft + textSize.width + widthMargin, - height: Math.max(textSize.height, markerDiam) - }; - - // ------------- - - var isFirstInRow; - if(!row){ - row = new pvc.visual.legend.BulletItemSceneRow(0); - isFirstInRow = true; - } else { - isFirstInRow = !row.items.length; - } - - var newRowWidth = row.size.width + itemClientSize[a_width]; // or bottom - if(!isFirstInRow){ - newRowWidth += itemPadding[a_width]; // separate from previous item - } - - // If not the first column of a row and the item does not fit - if(!isFirstInRow && (newRowWidth > maxRowWidth)){ - commitRow(/* isLast */ false); - - newRowWidth = itemClientSize[a_width]; - } - - // Add item to row - var rowSize = row.size; - rowSize.width = newRowWidth; - rowSize.height = Math.max(rowSize.height, itemClientSize[a_height]); - - var rowItemIndex = row.items.length; - row.items.push(itemScene); - - def.set(itemScene.vars, - 'row', row, // In logical "row" naming - 'rowIndex', rowItemIndex, // idem - 'clientSize', itemClientSize); - } - - function commitRow(isLast){ - var rowSize = row.size; - contentSize.height += rowSize.height; - if(rows.length){ - // Separate rows - contentSize.height += itemPadding[a_height]; - } - - contentSize.width = Math.max(contentSize.width, rowSize.width); - rows.push(row); - - // New row - if(!isLast){ - row = new pvc.visual.legend.BulletItemSceneRow(rows.length); - } - } - }, - - defaultGroupSceneType: function(){ - var GroupType = this._bulletGroupType; - if(!GroupType){ - GroupType = def.type(pvc.visual.legend.BulletGroupScene); - - // Apply legend group scene extensions - //this.panel()._extendSceneType('group', GroupType, ['...']); - - this._bulletGroupType = GroupType; - } - - return GroupType; - }, - - createGroup: function(keyArgs){ - var GroupType = this.defaultGroupSceneType(); - return new GroupType(this, keyArgs); - } -}); - -def -.type('pvc.visual.legend.BulletItemSceneRow') -.init(function(index){ - this.index = index; - this.items = []; - this.size = {width: 0, height: 0}; -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/legend/WaterfallBulletGroupScene.js b/pacotes/ccc2/pvc/visual/legend/WaterfallBulletGroupScene.js deleted file mode 100755 index 96cca14..0000000 --- a/pacotes/ccc2/pvc/visual/legend/WaterfallBulletGroupScene.js +++ /dev/null @@ -1,62 +0,0 @@ - -/** - * Initializes a waterfall legend bullet group scene. - * - * @name pvc.visual.legend.WaterfallBulletGroupScene - - * @extends pvc.visual.Scene - * - * @constructor - * @param {pvc.visual.legend.BulletRootScene} parent The parent bullet root scene. - * @param {object} [keyArgs] Keyword arguments. - * See {@link pvc.visual.Scene} for additional keyword arguments. - * @param {pv.visual.legend.renderer} [keyArgs.renderer] Keyword arguments. - */ -def -.type('pvc.visual.legend.WaterfallBulletGroupScene', pvc.visual.Scene) -.init(function(rootScene, keyArgs){ - - this.base(rootScene, keyArgs); - - this.extensionPrefix = def.get(keyArgs, 'extensionPrefix') || ''; - - var item = this.createItem({ - value: null, - rawValue: null, - label: def.get(keyArgs, 'label') - }); - - item.color = def.get(keyArgs, 'color'); -}) -.add(/** @lends pvc.visual.legend.WaterfallBulletGroupScene# */{ - hasRenderer: function(){ - return this._renderer; - }, - - renderer: function(renderer){ - if(renderer != null){ - this._renderer = renderer; - } - - return this._renderer; - }, - - itemSceneType: function(){ - var ItemType = this._itemSceneType; - if(!ItemType){ - ItemType = def.type(pvc.visual.legend.BulletItemScene); - - // Apply legend item scene extensions - this.panel()._extendSceneType('item', ItemType, ['isOn', 'isClickable', 'click']); - - this._itemSceneType = ItemType; - } - - return ItemType; - }, - - createItem: function(keyArgs){ - var ItemType = this.itemSceneType(); - return new ItemType(this, keyArgs); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/BarPlot.js b/pacotes/ccc2/pvc/visual/plot/BarPlot.js deleted file mode 100755 index 07d9d90..0000000 --- a/pacotes/ccc2/pvc/visual/plot/BarPlot.js +++ /dev/null @@ -1,13 +0,0 @@ - -/** - * Initializes a bar plot. - * - * @name pvc.visual.BarPlot - * @class Represents a bar plot. - * @extends pvc.visual.BarPlotAbstract - */ -def -.type('pvc.visual.BarPlot', pvc.visual.BarPlotAbstract) -.add({ - type: 'bar' -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/BarPlotAbstract.js b/pacotes/ccc2/pvc/visual/plot/BarPlotAbstract.js deleted file mode 100755 index de0a267..0000000 --- a/pacotes/ccc2/pvc/visual/plot/BarPlotAbstract.js +++ /dev/null @@ -1,86 +0,0 @@ -def.scope(function(){ - - /** - * Initializes an abstract bar plot. - * - * @name pvc.visual.BarPlotAbstract - * @class Represents an abstract bar plot. - * @extends pvc.visual.CategoricalPlot - */ - def - .type('pvc.visual.BarPlotAbstract', pvc.visual.CategoricalPlot) - .add({ - _getOptionsDefinition: function(){ - return pvc.visual.BarPlotAbstract.optionsDef; - } - }); - - pvc.visual.BarPlotAbstract.optionsDef = def.create( - pvc.visual.CategoricalPlot.optionsDef, { - - BarSizeRatio: { // for grouped bars - resolve: '_resolveFull', - cast: function(value){ - value = pvc.castNumber(value); - if(value == null){ - value = 1; - } else if(value < 0.05){ - value = 0.05; - } else if(value > 1){ - value = 1; - } - - return value; - }, - value: 0.9 - }, - - BarSizeMax: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - // default to v1 option - this._specifyChartOption(optionInfo, 'maxBarSize'); - return true; - } - }, - cast: function(value){ - value = pvc.castNumber(value); - if(value == null){ - value = Infinity; - } else if(value < 1){ - value = 1; - } - - return value; - }, - value: 2000 - }, - - BarStackedMargin: { // for stacked bars - resolve: '_resolveFull', - cast: function(value){ - value = pvc.castNumber(value); - if(value != null && value < 0){ - value = 0; - } - - return value; - }, - value: 0 - }, - - OverflowMarkersVisible: { - resolve: '_resolveFull', - cast: Boolean, - value: true - }, - - ValuesAnchor: { // override default value only - value: 'center' - } - - /* TODO valuesMask... - */ - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/BoxPlot.js b/pacotes/ccc2/pvc/visual/plot/BoxPlot.js deleted file mode 100755 index 5bc8597..0000000 --- a/pacotes/ccc2/pvc/visual/plot/BoxPlot.js +++ /dev/null @@ -1,73 +0,0 @@ -def.scope(function(){ - - /** - * Initializes a box plot. - * - * @name pvc.visual.BoxPlot - * @class Represents a box plot. - * @extends pvc.visual.CategoricalPlot - */ - def - .type('pvc.visual.BoxPlot', pvc.visual.CategoricalPlot) - .add({ - type: 'box', - - _getOptionsDefinition: function(){ - return pvc.visual.BoxPlot.optionsDef; - } - }); - - pvc.visual.BoxPlot.optionsDef = def.create( - pvc.visual.CategoricalPlot.optionsDef, - { - // NO Values Label! - - Stacked: { - resolve: null, - value: false - }, - - OrthoRole: { - value: ['median', 'lowerQuartil', 'upperQuartil', 'minimum', 'maximum'] // content of pvc.BoxplotChart.measureRolesNames - }, - - BoxSizeRatio: { - resolve: '_resolveFull', - cast: function(value){ - value = pvc.castNumber(value); - if(value == null){ - value = 1; - } else if(value < 0.05){ - value = 0.05; - } else if(value > 1){ - value = 1; - } - - return value; - }, - value: 1/3 - }, - - BoxSizeMax: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - // default to v1 option - this._specifyChartOption(optionInfo, 'maxBoxSize'); - return true; - } - }, - cast: function(value){ - value = pvc.castNumber(value); - if(value == null){ - value = Infinity; - } else if(value < 1){ - value = 1; - } - - return value; - }, - value: Infinity - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/BulletPlot.js b/pacotes/ccc2/pvc/visual/plot/BulletPlot.js deleted file mode 100755 index 1653a42..0000000 --- a/pacotes/ccc2/pvc/visual/plot/BulletPlot.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Initializes a bullet plot. - * - * @name pvc.visual.BulletPlot - * @class Represents a bullet plot. - * @extends pvc.visual.Plot - */ -def -.type('pvc.visual.BulletPlot', pvc.visual.Plot) -.add({ - type: 'bullet', - - _getOptionsDefinition: function(){ - return pvc.visual.BulletPlot.optionsDef; - } -}); - -pvc.visual.BulletPlot.optionsDef = def.create( - pvc.visual.Plot.optionsDef, { - ValuesVisible: { // override - value: true - }, - - ColorRole: { - value: null - } - }); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/CartesianPlot.js b/pacotes/ccc2/pvc/visual/plot/CartesianPlot.js deleted file mode 100755 index 963cd8d..0000000 --- a/pacotes/ccc2/pvc/visual/plot/CartesianPlot.js +++ /dev/null @@ -1,136 +0,0 @@ -def.scope(function(){ - - /** - * Initializes an abstract cartesian plot. - * - * @name pvc.visual.CartesianPlot - * @class Represents an abstract cartesian plot. - * @extends pvc.visual.Plot - */ - def - .type('pvc.visual.CartesianPlot', pvc.visual.Plot) - .add({ - _getOptionsDefinition: function(){ - return pvc.visual.CartesianPlot.optionsDef; - } - }); - - function castTrend(trend){ - // The trend plot itself does not have trends... - if(this.name === 'trend'){ - return null; - } - - var type = this.option('TrendType'); - if(!type && trend){ - type = trend.type; - } - - if(!type || type === 'none'){ - return null; - } - - if(!trend){ - trend = {}; - } else { - trend = Object.create(trend); - } - - trend.type = type; - - var label = this.option('TrendLabel'); - if(label !== undefined){ - trend.label = label; - } - - return trend; - } - - pvc.visual.CartesianPlot.optionsDef = def.create( - pvc.visual.Plot.optionsDef, { - BaseAxis: { - value: 1 - }, - - BaseRole: { - resolve: '_resolveFixed', - cast: String - }, - - OrthoAxis: { - resolve: function(optionInfo){ - if(this.globalIndex === 0){ - // plot0 must use ortho axis 0! - // This also ensures that the ortho axis 0 is created... - optionInfo.specify(1); - return true; - } - - return this._resolveFull(optionInfo); - }, - data: { - resolveV1: function(optionInfo){ - if(this.name === 'plot2' && - this.chart._allowV1SecondAxis && - this._chartOption('secondAxisIndependentScale')){ - optionInfo.specify(2); - } - return true; - } - }, - cast: function(value){ - value = pvc.castNumber(value); - if(value != null){ - value = def.between(value, 1, 10); - } else { - value = 1; - } - - return value; - }, - value: 1 - }, - - OrthoRole: { - resolve: pvc.options.resolvers([ - '_resolveFixed', - '_resolveDefault' - ]) - // String or string array - }, - - Trend: { - resolve: '_resolveFull', - data: { - resolveDefault: function(optionInfo){ - var type = this.option('TrendType'); - if(type){ - // Cast handles the rest - optionInfo.defaultValue({ - type: type - }); - return true; - } - } - }, - cast: castTrend - }, - - TrendType: { - resolve: '_resolveFull', - cast: pvc.parseTrendType - //value: 'none' - }, - - TrendLabel: { - resolve: '_resolveFull', - cast: String - }, - - NullInterpolationMode: { - resolve: '_resolveFull', - cast: pvc.parseNullInterpolationMode, - value: 'none' - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/CategoricalPlot.js b/pacotes/ccc2/pvc/visual/plot/CategoricalPlot.js deleted file mode 100755 index 83e7d95..0000000 --- a/pacotes/ccc2/pvc/visual/plot/CategoricalPlot.js +++ /dev/null @@ -1,35 +0,0 @@ -def.scope(function(){ - - /** - * Initializes an abstract categorical plot. - * - * @name pvc.visual.CategoricalPlot - * @class Represents an abstract categorical plot. - * @extends pvc.visual.CartesianPlot - */ - def - .type('pvc.visual.CategoricalPlot', pvc.visual.CartesianPlot) - .add({ - _getOptionsDefinition: function(){ - return pvc.visual.CategoricalPlot.optionsDef; - } - }); - - pvc.visual.CategoricalPlot.optionsDef = def.create( - pvc.visual.CartesianPlot.optionsDef, { - - Stacked: { - resolve: '_resolveFull', - cast: Boolean, - value: false - }, - - BaseRole: { - value: 'category' - }, - - OrthoRole: { // override - value: 'value' - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/HeatGridPlot.js b/pacotes/ccc2/pvc/visual/plot/HeatGridPlot.js deleted file mode 100755 index cfa7150..0000000 --- a/pacotes/ccc2/pvc/visual/plot/HeatGridPlot.js +++ /dev/null @@ -1,72 +0,0 @@ -def.scope(function(){ - - /** - * Initializes a heat grid plot. - * - * @name pvc.visual.HeatGridPlot - * @class Represents a heat grid plot. - * @extends pvc.visual.CategoricalPlot - */ - def - .type('pvc.visual.HeatGridPlot', pvc.visual.CategoricalPlot) - .add({ - type: 'heatGrid', - _getOptionsDefinition: function(){ - return pvc.visual.HeatGridPlot.optionsDef; - } - }); - - pvc.visual.HeatGridPlot.optionsDef = def.create( - pvc.visual.CategoricalPlot.optionsDef, - { - SizeRole: { - value: 'size' - }, - - SizeAxis: { - value: 1 - }, - - UseShapes: { - resolve: '_resolveFull', - cast: Boolean, - value: false - }, - - Shape: { - resolve: '_resolveFull', - cast: pvc.parseShape, - value: 'square' - }, - - NullShape: { - resolve: '_resolveFull', - cast: pvc.parseShape, - value: 'cross' - }, - - ValuesVisible: { // override - value: true - }, - - OrthoRole: { // override - value: 'series' - }, - - OrthoAxis: { // override - resolve: null - }, - - // Not supported - NullInterpolationMode: { - resolve: null, - value: 'none' - }, - - // Not supported - Stacked: { // override - resolve: null, - value: false - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/MetricPointPlot.js b/pacotes/ccc2/pvc/visual/plot/MetricPointPlot.js deleted file mode 100755 index 4398cb9..0000000 --- a/pacotes/ccc2/pvc/visual/plot/MetricPointPlot.js +++ /dev/null @@ -1,64 +0,0 @@ -def.scope(function(){ - - /** - * Initializes a metric XY plot. - * - * @name pvc.visual.MetricPointPlot - * @class Represents a metric point plot. - * @extends pvc.visual.MetricXYPlot - */ - def - .type('pvc.visual.MetricPointPlot', pvc.visual.MetricXYPlot) - .add({ - type: 'scatter', - _getOptionsDefinition: function(){ - return pvc.visual.MetricPointPlot.optionsDef; - } - }); - - function visibleData(type){ - return { - resolveV1: function(optionInfo){ - this._specifyChartOption(optionInfo, 'show' + type); - return true; - } - }; - } - - pvc.visual.MetricPointPlot.optionsDef = def.create( - pvc.visual.MetricXYPlot.optionsDef, { - SizeRole: { - resolve: '_resolveFixed', - value: 'size' - }, - - SizeAxis: { - resolve: '_resolveFixed', - value: 1 - }, - - Shape: { - resolve: '_resolveFull', - cast: pvc.parseShape, - value: 'circle' - }, - - DotsVisible: { - resolve: '_resolveFull', - data: visibleData('Dots'), - cast: Boolean, - value: false - }, - - LinesVisible: { - resolve: '_resolveFull', - data: visibleData('Lines'), - cast: Boolean, - value: false - }, - - ValuesAnchor: { // override - value: 'right' - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/MetricXYPlot.js b/pacotes/ccc2/pvc/visual/plot/MetricXYPlot.js deleted file mode 100755 index ba7db51..0000000 --- a/pacotes/ccc2/pvc/visual/plot/MetricXYPlot.js +++ /dev/null @@ -1,32 +0,0 @@ -def.scope(function(){ - - /** - * Initializes an abstract metric XY plot. - * - * @name pvc.visual.MetricXYPlot - * @class Represents an abstract metric XY plot. - * @extends pvc.visual.CartesianPlot - */ - def - .type('pvc.visual.MetricXYPlot', pvc.visual.CartesianPlot) - .add({ - _getOptionsDefinition: function(){ - return pvc.visual.MetricXYPlot.optionsDef; - } - }); - - pvc.visual.MetricXYPlot.optionsDef = def.create( - pvc.visual.CartesianPlot.optionsDef, { - BaseRole: { // override - value: 'x' - }, - - OrthoAxis: { // override -> value 1 - resolve: null - }, - - OrthoRole: { - value: 'y' - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/NormalizedBarPlot.js b/pacotes/ccc2/pvc/visual/plot/NormalizedBarPlot.js deleted file mode 100755 index 7122355..0000000 --- a/pacotes/ccc2/pvc/visual/plot/NormalizedBarPlot.js +++ /dev/null @@ -1,27 +0,0 @@ -def.scope(function(){ - - /** - * Initializes a normalized bar plot. - * - * @name pvc.visual.NormalizedBarPlot - * @class Represents a normalized bar plot. - * @extends pvc.visual.BarPlotAbstract - */ - def - .type('pvc.visual.NormalizedBarPlot', pvc.visual.BarPlotAbstract) - .add({ - type: 'bar', - _getOptionsDefinition: function(){ - return pvc.visual.NormalizedBarPlot.optionsDef; - } - }); - - pvc.visual.NormalizedBarPlot.optionsDef = def.create( - pvc.visual.BarPlotAbstract.optionsDef, - { - Stacked: { - resolve: null, - value: true - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/PiePlot.js b/pacotes/ccc2/pvc/visual/plot/PiePlot.js deleted file mode 100755 index 56573e5..0000000 --- a/pacotes/ccc2/pvc/visual/plot/PiePlot.js +++ /dev/null @@ -1,170 +0,0 @@ -def.scope(function(){ - - /** - * Initializes a pie plot. - * - * @name pvc.visual.PiePlot - * @class Represents a pie plot. - * @extends pvc.visual.Plot - */ - def - .type('pvc.visual.PiePlot', pvc.visual.Plot) - .add({ - type: 'pie', - - _getOptionsDefinition: function(){ - return pvc.visual.PiePlot.optionsDef; - } - }); - - pvc.visual.PiePlot.optionsDef = def.create( - pvc.visual.Plot.optionsDef, { - ActiveSliceRadius: { - resolve: '_resolveFull', - cast: pvc.PercentValue.parse, - value: new pvc.PercentValue(0.05) - }, - - ExplodedSliceRadius: { - resolve: '_resolveFull', - cast: pvc.PercentValue.parse, - value: 0 - }, - - ExplodedSliceIndex: { - resolve: '_resolveFull', - cast: pvc.castNumber, - value: null // all exploded when radius > 0 - }, - - ValuesAnchor: { // override - cast: pvc.parseAnchorWedge, - value: 'outer' - }, - - ValuesVisible: { // override - value: true - }, - - ValuesLabelStyle: { - resolve: function(optionInfo){ - var isV1Compat = this.chart.compatVersion() <= 1; - if(isV1Compat){ - optionInfo.specify('inside'); - return true; - } - - return this._resolveFull(optionInfo); - }, - cast: function(value) { - switch(value){ - case 'inside': - case 'linked': return value; - } - - if(pvc.debug >= 2){ - pvc.log("[Warning] Invalid 'ValuesLabelStyle' value: '" + value + "'."); - } - - return 'linked'; - }, - value: 'linked' - }, - - // Depends on being linked or not - // Examples: - // "{value} ({value.percent}) {category}" - // "{value}" - // "{value} ({value.percent})" - // "{#productId}" // Atom name - ValuesMask: { // OVERRIDE - resolve: '_resolveFull', - data: { - resolveDefault: function(optionInfo){ - optionInfo.defaultValue( - this.option('ValuesLabelStyle') === 'linked' ? - "{value} ({value.percent})" : - "{value}"); - return true; - } - } - }, - - /* Linked Label Style - * - * (| elbowX) (| anchorX) - * +----------------------------------+ (<-- baseY) - * | \ - * | (link outset) \ (targetX,Y) - * | +----+ label - * ----- <-- current outer radius |<-------->|<------------> - * | (link inset) (margin) (label size) - * - */ - - /** - * Percentage of the client radius that the - * link is inset in a slice. - */ - LinkInsetRadius: { - resolve: '_resolveFull', - cast: pvc.PercentValue.parse, - value: new pvc.PercentValue(0.05) - }, - - /** - * Percentage of the client radius that the - * link extends outwards from the slice, - * until it reaches the link "elbow". - */ - LinkOutsetRadius: { - resolve: '_resolveFull', - cast: pvc.PercentValue.parse, - value: new pvc.PercentValue(0.025) - }, - - /** - * Percentage of the client width that separates - * a link label from the link's anchor point. - *

- * Determines the width of the link segment that - * connects the "anchor" point with the "target" point. - * Includes the space for the small handle at the end. - *

- */ - LinkMargin: { - resolve: '_resolveFull', - cast: pvc.PercentValue.parse, - value: new pvc.PercentValue(0.025) - }, - - /** - * Link handle width, in em units. - */ - LinkHandleWidth: { - resolve: '_resolveFull', - cast: pvc.castNumber, - value: 0.5 - }, - - /** - * Percentage of the client width that is reserved - * for labels on each of the sides. - */ - LinkLabelSize: { - resolve: '_resolveFull', - cast: pvc.PercentValue.parse, - value: new pvc.PercentValue(0.15) - }, - - /** - * Minimum vertical space that separates consecutive link labels, - * in em units. - */ - LinkLabelSpacingMin: { - resolve: '_resolveFull', - cast: pvc.castNumber, - value: 0.5 - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/Plot.js b/pacotes/ccc2/pvc/visual/plot/Plot.js deleted file mode 100755 index 47626e7..0000000 --- a/pacotes/ccc2/pvc/visual/plot/Plot.js +++ /dev/null @@ -1,150 +0,0 @@ -def.scope(function(){ - - /** - * Initializes a plot. - * - * @name pvc.visual.Plot - * @class Represents a plot. - * @extends pvc.visual.OptionsBase - */ - def - .type('pvc.visual.Plot', pvc.visual.OptionsBase) - .init(function(chart, keyArgs){ - // Peek plot type-index - var typePlots = def.getPath(chart, ['plotsByType', this.type]); - var index = typePlots ? typePlots.length : 0; - - // Elements of the first plot (of any type) - // can be accessed without prefix. - // Peek chart's plotList (globalIndex is only set afterwards in addPlot) - var globalIndex = chart.plotList.length; - keyArgs = def.set(keyArgs, 'byNaked', !globalIndex); - - this.base(chart, this.type, index, keyArgs); - - // fills globalIndex - chart._addPlot(this); - - // ------------- - - // Last prefix has more precedence. - - // The plot id is always a valid prefix (type+index) - var prefixes = this.extensionPrefixes = [this.id]; - - if(!this.globalIndex){ - // Elements of the first plot (of any type) - // can be accessed without prefix - prefixes.push(''); - } - - // The plot name, if any is always a valid prefix (name) - if(this.name){ - prefixes.push(this.name); - } - }) - .add({ - // Override - _getOptionsDefinition: function(){ - return pvc.visual.Plot.optionsDef; - }, - - // Override - _resolveByNaked: pvc.options.specify(function(optionInfo){ - if(!this.globalIndex){ - return this._chartOption(def.firstLowerCase(optionInfo.name)); - } - }) - }); - - pvc.visual.Plot.optionsDef = { - // Box model options? - - Orientation: { - resolve: function(optionInfo){ - optionInfo.specify(this._chartOption('orientation') || 'vertical'); - return true; - }, - cast: String - }, - - ValuesVisible: { - resolve: '_resolveFull', - data: { - resolveV1: function(optionInfo){ - if(this.globalIndex === 0){ - var show = this._chartOption('showValues'); - if(show !== undefined){ - optionInfo.specify(show); - } else { - show = this.type !== 'point'; - optionInfo.defaultValue(show); - } - - return true; - } - } - }, - cast: Boolean, - value: false - }, - - ValuesAnchor: { - resolve: '_resolveFull', - cast: pvc.parseAnchor - }, - - ValuesFont: { - resolve: '_resolveFull', - cast: String, - value: '10px sans-serif' - }, - - // Each plot type must provide an appropriate default mask - // depending on its scene variable names - ValuesMask: { - resolve: '_resolveFull', - cast: String, - value: "{value}" - }, - - DataPart: { - resolve: '_resolveFixed', - cast: String, - value: '0' - }, - - // --------------- - - ColorRole: { - resolve: '_resolveFixed', - cast: String, - value: 'color' - }, - - ColorAxis: { - resolve: pvc.options.resolvers([ - function(optionInfo){ - if(this.globalIndex === 0){ - // plot0 must use color axis 0! - // This also ensures that the color axis 0 is created... - optionInfo.specify(1); - return true; - } - }, - '_resolveFull' - ]), - cast: function(value){ - value = pvc.castNumber(value); - if(value != null){ - value = def.between(value, 1, 10); - } else { - value = 1; - } - - return value; - }, - value: 1 - } - }; -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/PointPlot.js b/pacotes/ccc2/pvc/visual/plot/PointPlot.js deleted file mode 100755 index 95b893f..0000000 --- a/pacotes/ccc2/pvc/visual/plot/PointPlot.js +++ /dev/null @@ -1,58 +0,0 @@ -def.scope(function(){ - /** - * Initializes a point plot. - * - * @name pvc.visual.PointPlot - * @class Represents a Point plot. - * @extends pvc.visual.CategoricalPlot - */ - def - .type('pvc.visual.PointPlot', pvc.visual.CategoricalPlot) - .add({ - type: 'point', - _getOptionsDefinition: function(){ - return pvc.visual.PointPlot.optionsDef; - } - }); - - function visibleData(type, dv){ - return { - resolveV1: function(optionInfo){ - if(this.globalIndex === 0){ - if(!this._specifyChartOption(optionInfo, 'show' + type)){ - optionInfo.defaultValue(dv); - } - return true; - } - } - }; - } - - pvc.visual.PointPlot.optionsDef = def.create( - pvc.visual.CategoricalPlot.optionsDef, { - DotsVisible: { - resolve: '_resolveFull', - data: visibleData('Dots', true), - cast: Boolean, - value: false - }, - - LinesVisible: { - resolve: '_resolveFull', - data: visibleData('Lines', true), - cast: Boolean, - value: false - }, - - AreasVisible: { - resolve: '_resolveFull', - data: visibleData('Areas', false), - cast: Boolean, - value: false - }, - - ValuesAnchor: { // override - value: 'right' - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/plot/WaterfallPlot.js b/pacotes/ccc2/pvc/visual/plot/WaterfallPlot.js deleted file mode 100755 index 0665291..0000000 --- a/pacotes/ccc2/pvc/visual/plot/WaterfallPlot.js +++ /dev/null @@ -1,63 +0,0 @@ -def.scope(function(){ - - /** - * Initializes a waterfall plot. - * - * @name pvc.visual.WaterfallPlot - * @class Represents a waterfall plot. - * @extends pvc.visual.BarPlotAbstract - */ - def - .type('pvc.visual.WaterfallPlot', pvc.visual.BarPlotAbstract) - .add({ - type: 'water', - _getOptionsDefinition: function(){ - return pvc.visual.WaterfallPlot.optionsDef; - } - }); - - pvc.visual.WaterfallPlot.optionsDef = def.create( - pvc.visual.BarPlotAbstract.optionsDef, - { - Stacked: { // override - resolve: null, - value: true - }, - - TotalLineLabel: { - resolve: '_resolveFull', - cast: String, - value: "Accumulated" - }, - - TotalValuesVisible: { - resolve: '_resolveFull', - data: { - // Dynamic default - resolveDefault: function(optionInfo){ - optionInfo.defaultValue(this.option('ValuesVisible')); - return true; - } - }, - cast: Boolean - }, - - Direction: { // up/down - resolve: '_resolveFull', - cast: pvc.parseWaterDirection, - value: 'down' - }, - - AreasVisible: { - resolve: '_resolveFull', - cast: Boolean, - value: true - }, - - AllCategoryLabel: { - resolve: '_resolveFull', - cast: String, - value: "All" - } - }); -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/sign/Area.js b/pacotes/ccc2/pvc/visual/sign/Area.js deleted file mode 100755 index f47f8b1..0000000 --- a/pacotes/ccc2/pvc/visual/sign/Area.js +++ /dev/null @@ -1,81 +0,0 @@ - -def.type('pvc.visual.Area', pvc.visual.Sign) -.init(function(panel, protoMark, keyArgs){ - - var pvMark = protoMark.add(pv.Area); - - if(!keyArgs) { keyArgs = {}; } - - keyArgs.freeColor = true; - - this.base(panel, pvMark, keyArgs); - - var antialias = def.get(keyArgs, 'antialias', true); - - this - .lock('segmented', 'smart') // fixed, not inherited - .lock('antialias', antialias) - ; - - if(!def.get(keyArgs, 'freePosition', false)){ - var basePosProp = panel.isOrientationVertical() ? "left" : "bottom", - orthoPosProp = panel.anchorOrtho(basePosProp), - orthoLenProp = panel.anchorOrthoLength(orthoPosProp); - - /* Positions */ - this - ._lockDynamic(basePosProp, 'x') // ex: left - ._lockDynamic(orthoPosProp, 'y') // ex: bottom - ._lockDynamic(orthoLenProp, 'dy') // ex: height - ; - } - - /* Colors */ - this._bindProperty('fillStyle', 'fillColor', 'color'); - - // These really have no real meaning in the area and should not be used. - // If lines are desired, they should be created with linesVisible of LineChart - this.lock('strokeStyle', null) - .lock('lineWidth', 0) - ; -}) -.add({ - _addInteractive: function(keyArgs){ - keyArgs = def.setDefaults(keyArgs, - 'noTooltip', true); - - this.base(keyArgs); - }, - - /* Sign Spatial Coordinate System - * -> Cartesian coordinates - * -> Grows Up, vertically, and Right, horizontally - * -> Independent of the chart's orientation - * -> X - horizontal axis - * -> Y - vertical axis - * - * y ^ - * ^ dY | - * | - y - * | - * o-----> x - */ - x: function(){ return 0; }, - y: function(){ return 0; }, - dy: function(){ return 0; }, - - /* COLOR */ - /** - * @override - */ - interactiveColor: function(color, type){ - if(type === 'fill' && - this.showsSelection() && - this.scene.anySelected() && - !this.scene.isSelected()) { - return this.dimColor(color, type); - } - - return this.base(color, type); - } -}); diff --git a/pacotes/ccc2/pvc/visual/sign/Bar.js b/pacotes/ccc2/pvc/visual/sign/Bar.js deleted file mode 100755 index 80820d7..0000000 --- a/pacotes/ccc2/pvc/visual/sign/Bar.js +++ /dev/null @@ -1,92 +0,0 @@ - -def.type('pvc.visual.Bar', pvc.visual.Sign) -.init(function(panel, protoMark, keyArgs){ - - var pvMark = protoMark.add(pv.Bar); - - keyArgs = def.setDefaults(keyArgs, 'freeColor', false); - - this.base(panel, pvMark, keyArgs); - - this.normalStroke = def.get(keyArgs, 'normalStroke', false); - - this._bindProperty('lineWidth', 'strokeWidth'); -}) -.prototype -.property('strokeWidth') -.constructor -.add({ - /* COLOR */ - /** - * @override - */ - normalColor: function(color, type){ - if(type === 'stroke' && !this.normalStroke){ - return null; - } - - return color; - }, - - /** - * @override - */ - interactiveColor: function(color, type){ - var scene = this.scene; - - if(type === 'stroke'){ - if(scene.isActive){ - return color.brighter(1.3).alpha(0.7); - } - - if(!this.normalStroke){ - return null; - } - - if(this.showsSelection() && scene.anySelected() && !scene.isSelected()) { - if(this.isActiveSeriesAware && scene.isActiveSeries()) { - return pv.Color.names.darkgray.darker().darker(); - } - - return this.dimColor(color, type); - - } - - if(this.isActiveSeriesAware && scene.isActiveSeries()){ - return color.brighter(1).alpha(0.7); - } - - } else if(type === 'fill'){ - if(scene.isActive) { - return color.brighter(0.2).alpha(0.8); - } - - if(this.showsSelection() && scene.anySelected() && !scene.isSelected()) { - if(this.isActiveSeriesAware && scene.isActiveSeries()) { - return pv.Color.names.darkgray.darker(2).alpha(0.8); - } - - return this.dimColor(color, type); - } - - if(this.isActiveSeriesAware && scene.isActiveSeries()){ - return color.brighter(0.2).alpha(0.8); - } - } - - return this.base(color, type); - }, - - /* STROKE WIDTH */ - defaultStrokeWidth: function(){ - return 0.5; - }, - - interactiveStrokeWidth: function(strokeWidth){ - if(this.scene.isActive){ - return Math.max(1, strokeWidth) * 1.3; - } - - return strokeWidth; - } -}); diff --git a/pacotes/ccc2/pvc/visual/sign/BasicSign.js b/pacotes/ccc2/pvc/visual/sign/BasicSign.js deleted file mode 100755 index 8270827..0000000 --- a/pacotes/ccc2/pvc/visual/sign/BasicSign.js +++ /dev/null @@ -1,161 +0,0 @@ - -(function(){ - - pv.Mark.prototype.getSign = function(){ - return this.sign || createBasic(this); - }; - - pv.Mark.prototype.getScene = function(){ - return this.getSign().scene; - }; - - function createBasic(pvMark){ - var as = getAncestorSign(pvMark) || - def.assert("There must exist an ancestor sign"); - var bs = new pvc.visual.BasicSign(as.panel, pvMark); - var i; - var s = pvMark.scene; - if(s && (i = pvMark.index) != null && i >= 0){ - // Mark is already rendering; build the current instance - bs._buildInstance(pvMark, s[i], /*lateCall*/ true); - } - return bs; - } - - // Obtains the first sign accessible from the argument mark. - function getAncestorSign(pvMark){ - var sign; - do{ - pvMark = pvMark.parent; - } while(pvMark && !(sign = pvMark.sign) && (!pvMark.proto || !(sign = pvMark.proto.sign))); - - return sign; - } - - // Used to wrap a mark, dynamically, - // with minimal impact and functionality. - def.type('pvc.visual.BasicSign') - .init(function(panel, pvMark){ - this.chart = panel.chart; - this.panel = panel; - this.pvMark = pvMark; - - !pvMark.sign || def.assert("Mark already has an attached Sign."); - - pvMark.sign = this; - - /* Intercept the protovis mark's buildInstance */ - - // Avoid doing a function bind, cause buildInstance is a very hot path - pvMark.__buildInstance = pvMark.buildInstance; - pvMark.buildInstance = this._dispatchBuildInstance; - }) - .add({ - // Defines a local property on the underlying protovis mark - localProperty: function(name, type){ - this.pvMark.localProperty(name, type); - return this; - }, - - lock: function(name, value){ - return this.lockMark(name, this._bindWhenFun(value)); - }, - - optional: function(name, value, tag){ - return this.optionalMark(name, this._bindWhenFun(value), tag); - }, - - // ------------- - - lockMark: function(name, value){ - this.pvMark.lock(name, value); - return this; - }, - - optionalMark: function(name, value, tag){ - this.pvMark[name](value, tag); - return this; - }, - - // -------------- - - delegate: function(dv, tag){ - return this.pvMark.delegate(dv, tag); - }, - - delegateExtension: function(dv){ - return this.pvMark.delegate(dv, pvc.extensionTag); - }, - - hasDelegate: function(tag){ - return this.pvMark.hasDelegate(tag); - }, - - // Using it is a smell... - // hasExtension: function(){ - // return this.pvMark.hasDelegate(pvc.extensionTag); - // }, - - // ------------- - - _bindWhenFun: function(value){ - if(typeof value === 'function'){ - /* return value.bind(this); */ - return function(){ - var sign = this.getSign(); - return value.apply(sign, arguments); - }; - } - - return value; - }, - - _lockDynamic: function(name, method){ - /* def.methodCaller('' + method, this) */ - var me = this; - return this.lockMark( - name, - function(){ - var sign = this.getSign(); - var m = sign[method] || - me [method] || - def.assert("No method with name '" + method + "' is defined"); - - return m.apply(sign, arguments); - }); - }, - - // -------------- - - /* SCENE MAINTENANCE */ - _dispatchBuildInstance: function(instance){ - // this: the mark - this.sign._buildInstance(this, instance); - }, - - _buildInstance: function(mark, instance, lateCall){ - - var scene = instance.data; - var index = scene ? scene.childIndex() : 0; - - this.pvInstance = instance; - this.scene = scene; - this.index = index < 0 ? 0 : index; - - /* - * Update the scene's render id, - * which possibly invalidates per-render - * cached data. - */ - /*global scene_renderId:true */ - scene_renderId.call(scene, mark.renderId()); - - /* state per: sign & scene & render */ - this.state = {}; - - if(!lateCall){ - mark.__buildInstance.call(mark, instance); - } - } - }); -}()); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/sign/Dot.js b/pacotes/ccc2/pvc/visual/sign/Dot.js deleted file mode 100755 index c9dabca..0000000 --- a/pacotes/ccc2/pvc/visual/sign/Dot.js +++ /dev/null @@ -1,118 +0,0 @@ - -def.type('pvc.visual.Dot', pvc.visual.Sign) -.init(function(panel, parentMark, keyArgs){ - - var pvMark = parentMark.add(pv.Dot); - - var protoMark = def.get(keyArgs, 'proto'); - if(protoMark){ - pvMark.extend(protoMark); - } - - keyArgs = def.setDefaults(keyArgs, 'freeColor', false); - - this.base(panel, pvMark, keyArgs); - - if(!def.get(keyArgs, 'freePosition', false)){ - var basePosProp = panel.isOrientationVertical() ? "left" : "bottom", - orthoPosProp = panel.anchorOrtho(basePosProp); - - this/* Positions */ - ._lockDynamic(orthoPosProp, 'y') - ._lockDynamic(basePosProp, 'x'); - } - - this/* Shape & Size */ - ._bindProperty('shape', 'shape' ) - ._bindProperty('shapeRadius', 'radius') - ._bindProperty('shapeSize', 'size' ) - - /* Colors & Line */ - .optional('strokeDasharray', undefined) // Break inheritance - .optional('lineWidth', 1.5) // Idem - ; -}) -.prototype -.property('size') -.constructor -.add({ - /* Sign Spatial Coordinate System - * -> Cartesian coordinates - * -> Grows Up, vertically, and Right, horizontally - * -> Independent of the chart's orientation - * -> X - horizontal axis - * -> Y - vertical axis - * - * y - * ^ - * | - * | - * o-----> x - */ - y: function(){ return 0; }, - x: function(){ return 0; }, - - shape: function(){ - return this.delegateExtension(); - }, - - radius: function(){ - // Store extended value, if any - // See #sizeCore - this.state.radius = this.delegateExtension(); - }, - - /* SIZE */ - baseSize: function(){ - /* Radius was specified? */ - var radius = this.state.radius; - if(radius != null) { - return radius * radius; - } - - return this.base(); - }, - - defaultSize: function(){ - return 12; - }, - - interactiveSize: function(size){ - if(this.scene.isActive){ - return Math.max(size, 5) * 2.5; - } - - return size; - }, - - /* COLOR */ - - /** - * @override - */ - interactiveColor: function(color, type){ - var scene = this.scene; - if(scene.isActive) { - if(type === 'stroke') { - return color.brighter(1); - } - } else if(this.showsSelection() && scene.anySelected() && !scene.isSelected()) { - - if(this.isActiveSeriesAware && scene.isActiveSeries()) { - //return color.darker(1.5); - return color.alpha(0.8); -// switch(type){ -// case 'fill': return pv.Color.names.darkgray.darker().darker(); -// case 'stroke': return color; -// } - } else { - switch(type) { - case 'fill': return this.dimColor(color, type); - case 'stroke': return color.alpha(0.45); - } - } - } - - return this.base(color, type); - } -}); diff --git a/pacotes/ccc2/pvc/visual/sign/Label.js b/pacotes/ccc2/pvc/visual/sign/Label.js deleted file mode 100755 index 54b9918..0000000 --- a/pacotes/ccc2/pvc/visual/sign/Label.js +++ /dev/null @@ -1,24 +0,0 @@ - -def.type('pvc.visual.Label', pvc.visual.Sign) -.init(function(panel, protoMark, keyArgs){ - - var pvMark = protoMark.add(pv.Label); - - this.base(panel, pvMark, keyArgs); -}) -.add({ - _addInteractive: function(keyArgs){ - keyArgs = def.setDefaults(keyArgs, - 'noSelect', true, - 'noHover', true, - 'noTooltip', true, - 'noClick', true, - 'noDoubleClick', true); - - this.base(keyArgs); - }, - - defaultColor: function(type){ - return pv.Color.names.black; - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/sign/Line.js b/pacotes/ccc2/pvc/visual/sign/Line.js deleted file mode 100755 index 7284e0f..0000000 --- a/pacotes/ccc2/pvc/visual/sign/Line.js +++ /dev/null @@ -1,93 +0,0 @@ - -def.type('pvc.visual.Line', pvc.visual.Sign) -.init(function(panel, protoMark, keyArgs){ - - var pvMark = protoMark.add(pv.Line); - - this.base(panel, pvMark, keyArgs); - - this.lock('segmented', 'smart') // fixed - .lock('antialias', true) - ; - - if(!def.get(keyArgs, 'freePosition', false)){ - var basePosProp = panel.isOrientationVertical() ? "left" : "bottom", - orthoPosProp = panel.anchorOrtho(basePosProp); - - this/* Positions */ - ._lockDynamic(orthoPosProp, 'y') - ._lockDynamic(basePosProp, 'x'); - } - - this/* Colors & Line */ - ._bindProperty('strokeStyle', 'strokeColor', 'color') - ._bindProperty('lineWidth', 'strokeWidth') - ; - - // Segmented lines use fill color instead of stroke...so this doesn't work. - //this.pvMark.lineCap('square'); -}) -.prototype -.property('strokeWidth') -.constructor -.add({ - _addInteractive: function(keyArgs){ - keyArgs = def.setDefaults(keyArgs, - 'noTooltip', true); - - this.base(keyArgs); - }, - - /* Sign Spatial Coordinate System - * -> Cartesian coordinates - * -> Grows Up, vertically, and Right, horizontally - * -> Independent of the chart's orientation - * -> X - horizontal axis - * -> Y - vertical axis - * - * y - * ^ - * | - * | - * o-----> x - */ - y: function(){ return 0; }, - x: function(){ return 0; }, - - /* STROKE WIDTH */ - defaultStrokeWidth: function(){ - return 1.5; - }, - - interactiveStrokeWidth: function(strokeWidth){ - if(this.isActiveSeriesAware && this.scene.isActiveSeries()){ - /* - Ensure a normal width of at least 1, - * - Double and a half that - */ - return Math.max(1, strokeWidth) * 2.5; - } - - return strokeWidth; - }, - - /* STROKE COLOR */ - /** - * @override - */ - interactiveColor: function(color, type){ - var scene = this.scene; - if(this.showsSelection() && scene.anySelected() && !scene.isSelected()) { - - if(this.isActiveSeriesAware && scene.isActiveSeries()) { - //return color.darker(1.5); - return pv.Color.names.darkgray.darker().darker(); - } - - if(type === 'stroke'){ - return this.dimColor(color, type); - } - } - - return this.base(color, type); - } -}); diff --git a/pacotes/ccc2/pvc/visual/sign/Panel.js b/pacotes/ccc2/pvc/visual/sign/Panel.js deleted file mode 100755 index 19637c0..0000000 --- a/pacotes/ccc2/pvc/visual/sign/Panel.js +++ /dev/null @@ -1,25 +0,0 @@ - -def.type('pvc.visual.Panel', pvc.visual.Sign) -.init(function(panel, protoMark, keyArgs){ - var pvPanel = def.get(keyArgs, 'panel'); - if(!pvPanel){ - var pvPanelType = def.get(keyArgs, 'panelType') || pv.Panel; - - pvPanel = protoMark.add(pvPanelType); - } - - this.base(panel, pvPanel, keyArgs); -}) -.add({ - _addInteractive: function(keyArgs){ - var t = true; - keyArgs = def.setDefaults(keyArgs, - 'noSelect', t, - 'noHover', t, - 'noTooltip', t, - 'noClick', t, - 'noDoubleClick', t); - - this.base(keyArgs); - } -}); \ No newline at end of file diff --git a/pacotes/ccc2/pvc/visual/sign/PieSlice.js b/pacotes/ccc2/pvc/visual/sign/PieSlice.js deleted file mode 100755 index 12a78f1..0000000 --- a/pacotes/ccc2/pvc/visual/sign/PieSlice.js +++ /dev/null @@ -1,123 +0,0 @@ - - -pv.PieSlice = function(){ - pv.Wedge.call(this); -}; - -pv.PieSlice.prototype = pv.extend(pv.Wedge); - -// There's already a Wedge#midAngle method -// but it doesn't work well when end-angle isn't explicitly set, -// so we override the method. -pv.PieSlice.prototype.midAngle = function(){ - var instance = this.instance(); - return instance.startAngle + (instance.angle / 2); -}; - - -def.type('pvc.visual.PieSlice', pvc.visual.Sign) -.init(function(panel, protoMark, keyArgs){ - - var pvMark = protoMark.add(pv.PieSlice); - - keyArgs = def.setDefaults(keyArgs, 'freeColor', false); - - this.base(panel, pvMark, keyArgs); - - this._activeOffsetRadius = def.get(keyArgs, 'activeOffsetRadius', 0); - this._center = def.get(keyArgs, 'center'); - - this/* Colors */ - .optional('lineWidth', 0.6) - ._bindProperty('angle', 'angle') - ._lockDynamic('bottom', 'y') - ._lockDynamic('left', 'x') - .lock('top', null) - .lock('right', null) - ; -}) -.prototype -.property('offsetRadius') -.constructor -.add({ - // Ensures that it is evaluated before x and y - angle: function(){ - return 0; - }, - - x: function(){ - return this._center.x + this._offsetSlice('cos'); - }, - - y: function(){ - return this._center.y - this._offsetSlice('sin'); - }, - - // ~ midAngle -> (endAngle + startAngle) / 2 - _offsetSlice: function(fun) { - var offset = this._getOffsetRadius(); - if(offset !== 0){ - offset = offset * Math[fun](this.pvMark.midAngle()); - } - - return offset; - }, - - // Get and cache offsetRadius - _getOffsetRadius: function(){ - var offset = this.state.offsetRadius; - if(offset == null){ - offset = (this.state.offsetRadius = this.offsetRadius() || 0); - } - - return offset; - }, - - /* COLOR */ - - /** - * @override - */ - defaultColor: function(type){ - if(type === 'stroke'){ - return null; - } - - return this.base(type); - }, - - /** - * @override - */ - interactiveColor: function(color, type){ - var scene = this.scene; - if(scene.isActive) { - switch(type) { - // Like the bar chart - case 'fill': return color.brighter(0.2).alpha(0.8); - case 'stroke': return color.brighter(1.3).alpha(0.7); - } - } else if(this.showsSelection() && scene.anySelected() && !scene.isSelected()) { - //case 'stroke': // ANALYZER requirements, so until there's no way to configure it... - if(type === 'fill') { - return this.dimColor(color, type); - } - } - - return this.base(color, type); - }, - - /* Offset */ - baseOffsetRadius: function(){ - // There's no extension point for this - return 0; - }, - - interactiveOffsetRadius: function(offsetRadius){ - if(this.scene.isActive){ - return offsetRadius + this._activeOffsetRadius; - } - - return offsetRadius; - } -}); diff --git a/pacotes/ccc2/pvc/visual/sign/Rule.js b/pacotes/ccc2/pvc/visual/sign/Rule.js deleted file mode 100755 index 6673645..0000000 --- a/pacotes/ccc2/pvc/visual/sign/Rule.js +++ /dev/null @@ -1,60 +0,0 @@ - -def.type('pvc.visual.Rule', pvc.visual.Sign) -.init(function(panel, parentMark, keyArgs){ - - var pvMark = parentMark.add(pv.Rule); - - var protoMark = def.get(keyArgs, 'proto'); - if(protoMark){ - pvMark.extend(protoMark); - //pvMark.duckExtension(protoMark, pvc.extensionTag); - } - - this.base(panel, pvMark, keyArgs); - - if(!def.get(keyArgs, 'freeStyle')){ - this/* Colors & Line */ - ._bindProperty('strokeStyle', 'strokeColor', 'color') - ._bindProperty('lineWidth', 'strokeWidth') - ; - } -}) -.prototype -.property('strokeWidth') -.constructor -.add({ - _addInteractive: function(keyArgs){ - keyArgs = def.setDefaults(keyArgs, - 'noHover', true, - 'noSelect', true, - 'noTooltip', true, - 'noClick', true, - 'noDoubleClick', true); - - this.base(keyArgs); - }, - - /* STROKE WIDTH */ - defaultStrokeWidth: function(){ - return 1; - }, - - interactiveStrokeWidth: function(strokeWidth){ - if(this.scene.isActive){ - return Math.max(1, strokeWidth) * 2.2; - } - - return strokeWidth; - }, - - /* STROKE COLOR */ - interactiveColor: function(color, type){ - var scene = this.scene; - - if(!scene.isActive && this.showsSelection() && scene.anySelected() && scene.datum && !scene.isSelected()) { - return this.dimColor(color, type); - } - - return this.base(color, type); - } -}); diff --git a/pacotes/ccc2/pvc/visual/sign/Sign.js b/pacotes/ccc2/pvc/visual/sign/Sign.js deleted file mode 100755 index f161119..0000000 --- a/pacotes/ccc2/pvc/visual/sign/Sign.js +++ /dev/null @@ -1,381 +0,0 @@ - -def.type('pvc.visual.Sign', pvc.visual.BasicSign) -.init(function(panel, pvMark, keyArgs){ - - this.base(panel, pvMark, keyArgs); - - this.bits = 0; - - var extensionIds = def.get(keyArgs, 'extensionId'); - if(extensionIds != null){ // empty string is a valid extension id. - this.extensionAbsIds = def.array.to(panel._makeExtensionAbsId(extensionIds)); - } - - this.isActiveSeriesAware = def.get(keyArgs, 'activeSeriesAware', true) && - !!this.chart.visualRoles('series', {assertExists: false}); - - /* Extend the pv mark */ - var wrapper = def.get(keyArgs, 'wrapper'); - if(!wrapper){ - wrapper = function(f){ - return function(scene){ - return f.call(panel._getContext(pvMark), scene); - }; - }; - } - pvMark.wrapper(wrapper); - - if(!def.get(keyArgs, 'freeColor', true)){ - this._bindProperty('fillStyle', 'fillColor', 'color') - ._bindProperty('strokeStyle', 'strokeColor', 'color') - ; - } -}) -.postInit(function(panel, pvMark, keyArgs){ - - panel._addSign(this); - - this._addInteractive(keyArgs); -}) -.add({ - // To be called on prototype - property: function(name){ - var upperName = def.firstUpperCase(name); - var baseName = 'base' + upperName; - var defName = 'default' + upperName; - var normalName = 'normal' + upperName; - var interName = 'interactive' + upperName; - - var methods = {}; - - // color - methods[name] = function(arg){ - delete this._finished; - - var value; - this._arg = arg; // for use in calling default methods (see #_bindProperty) - try{ - value = this[baseName](arg); - if(value == null){ // undefined included - return null; - } - - if(this.hasOwnProperty('_finished')){ - return value; - } - - if(this.showsInteraction() && this.scene.anyInteraction()) { - // interactiveColor - value = this[interName](value, arg); - } else { - // normalColor - value = this[normalName](value, arg); - } - } finally{ - delete this._arg; - } - - return value; - }; - - // baseColor - methods[baseName] = function(arg){ - // Override this method if user extension - // should not always be called. - // It is possible to call the default method directly, if needed. - - // defName is installed as a user extension and - // is called if the user hasn't extended... - return this.delegateExtension(); - }; - - // defaultColor - methods[defName] = function(arg){ return; }; - - // normalColor - methods[normalName] = function(value, arg){ return value; }; - - // interactiveColor - methods[interName] = function(value, arg){ return value; }; - - this.constructor.add(methods); - - return this; - }, - - // Call this function with a final property value - // to ensure that it will not be processed anymore - finished: function(value){ - this._finished = true; - return value; - }, - - /* Extensibility */ - /** - * Any protovis properties that have been specified - * before the call to this method - * are either locked or are defaults. - * - * This method applies user extensions to the protovis mark. - * Default properties are replaced. - * Locked properties are respected. - * - * Any function properties that are specified - * after the call to this method - * will have access to the user extension by - * calling {@link pv.Mark#delegate}. - */ - applyExtensions: function(){ - if(!this._extended){ - this._extended = true; - - var extensionAbsIds = this.extensionAbsIds; - if(extensionAbsIds){ - extensionAbsIds.forEach(function(extensionAbsId){ - this.panel.extendAbs(this.pvMark, extensionAbsId); - }, this); - } - } - - return this; - }, - - // ------------- - - intercept: function(name, fun){ - return this._intercept(name, fun.bind(this)); - }, - - // ------------- - - lockDimensions: function(){ - this.pvMark - .lock('left') - .lock('right') - .lock('top') - .lock('bottom') - .lock('width') - .lock('height'); - - return this; - }, - - // ------------- - _extensionKeyArgs: {tag: pvc.extensionTag}, - - _bindProperty: function(pvName, prop, realProp){ - var me = this; - - if(!realProp){ - realProp = prop; - } - - var defaultPropName = "default" + def.firstUpperCase(realProp); - if(def.fun.is(this[defaultPropName])){ - // Intercept with default method first, before extensions, - // so that extensions, when ?existent?, can delegate to the default. - - // Extensions will be applied next. - - // If there already exists an applied extension then - // do not install the default (used by legend proto defaults, - // that should act like user extensions, and not be shadowed by prop defaults). - - // Mark default as pvc.extensionTag, - // so that it is chosen when - // the user hasn't specified an extension point. - - if(!this.pvMark.hasDelegateValue(pvName, pvc.extensionTag)){ - var defaultMethodCaller = function(){ - return me[defaultPropName](me._arg); - }; - - this.pvMark.intercept( - pvName, - defaultMethodCaller, - this._extensionKeyArgs); - } - } - - // Intercept with main property method - // Do not pass arguments, cause property methods do not use them, - // they use this.scene instead. - // The "arg" argument can only be specified explicitly, - // like in strokeColor -> color and fillColor -> color, - // via "helper property methods" that ?fix? the argument. - // In these cases, 'strokeColor' is the "prop", while - // "color" is the "realProp". - function mainMethodCaller(){ - return me[prop](); - } - - return this._intercept(pvName, mainMethodCaller); - }, - - _intercept: function(name, fun){ - var mark = this.pvMark; - - // Apply all extensions, in order - - var extensionAbsIds = this.extensionAbsIds; - if(extensionAbsIds){ - def - .query(extensionAbsIds) - .select(function(extensionAbsId){ - return this.panel._getExtensionAbs(extensionAbsId, name); - }, this) - .where(def.notUndef) - .each(function(extValue){ - extValue = mark.wrap(extValue, name); - - // Gets set on the mark; We intercept it afterwards. - // Mark with the pvc.extensionTag so that it is - // possible to filter extensions. - mark.intercept(name, extValue, this._extensionKeyArgs); - }, this); - } - - // Intercept with specified function (may not be a property function) - - (mark._intercepted || (mark._intercepted = {}))[name] = true; - - mark.intercept(name, fun); - - return this; - } -}) -.prototype -.property('color') -.constructor -.add({ - _bitShowsActivity: 2, - _bitShowsSelection: 4, - _bitShowsInteraction: 4 | 2, // 6 - _bitShowsTooltip: 8, - _bitSelectable: 16, - _bitHoverable: 32, - _bitClickable: 64, - _bitDoubleClickable: 128, - - showsInteraction: function(){ return (this.bits & this._bitShowsInteraction) !== 0; }, - showsActivity: function(){ return (this.bits & this._bitShowsActivity ) !== 0; }, - showsSelection: function(){ return (this.bits & this._bitShowsSelection ) !== 0; }, - showsTooltip: function(){ return (this.bits & this._bitShowsTooltip ) !== 0; }, - isSelectable: function(){ return (this.bits & this._bitSelectable ) !== 0; }, - isHoverable: function(){ return (this.bits & this._bitHoverable ) !== 0; }, - isClickable: function(){ return (this.bits & this._bitClickable ) !== 0; }, - isDoubleClickable: function(){ return (this.bits & this._bitDoubleClickable ) !== 0; }, - - extensionAbsIds: null, - - _addInteractive: function(keyArgs){ - var panel = this.panel, - pvMark = this.pvMark, - chart = this.chart, - options = chart.options; - - var bits = this.bits; - bits |= this._bitShowsInteraction; - - if(chart._tooltipEnabled && !def.get(keyArgs, 'noTooltip')){ - bits |= this._bitShowsTooltip; - - this.panel._addPropTooltip(pvMark, def.get(keyArgs, 'tooltipArgs')); - } - - var clickSelectable = false; - var clickable = false; - - if(options.selectable || options.hoverable){ - if(options.selectable && !def.get(keyArgs, 'noSelect')){ - bits |= this._bitSelectable; - clickSelectable = !def.get(keyArgs, 'noClickSelect') && - chart._canSelectWithClick(); - } - - if(options.hoverable && !def.get(keyArgs, 'noHover')){ - bits |= this._bitHoverable; - - panel._addPropHoverable(pvMark); - } - } - - // By default interaction is SHOWN if the sign - // is sensitive to interactive events. - - // This must be after the previous options, that affect bits with _bitShowsInteraction - var showsInteraction = def.get(keyArgs, 'showsInteraction'); - if(showsInteraction != null){ - if(showsInteraction){ - bits |= this._bitShowsInteraction; - } else { - bits &= ~this._bitShowsInteraction; - } - } - - var showsActivity = def.get(keyArgs, 'showsActivity'); - if(showsActivity != null){ - if(showsActivity){ - bits |= this._bitShowsActivity; - } else { - bits &= ~this._bitShowsActivity; - } - } - - var showsSelection = def.get(keyArgs, 'showsSelection'); - if(showsSelection != null){ - if(showsSelection){ - bits |= this._bitShowsSelection; - } else { - bits &= ~this._bitShowsSelection; - } - } - - if(!def.get(keyArgs, 'noClick') && panel._isClickable()){ - bits |= this._bitClickable; - clickable = true; - } - - if(clickSelectable || clickable){ - panel._addPropClick(pvMark); - } - - if(!def.get(keyArgs, 'noDoubleClick') && panel._isDoubleClickable()){ - bits |= this._bitDoubleClickable; - - panel._addPropDoubleClick(pvMark); - } - - this.bits = bits; - }, - - /* COLOR */ - fillColor: function(){ - return this.color('fill'); - }, - - strokeColor: function(){ - return this.color('stroke'); - }, - - defaultColor: function(/*type*/){ - return this.defaultColorSceneScale()(this.scene); - }, - - dimColor: function(color/*, type*/){ - return pvc.toGrayScale(color, -0.3, null, null); // ANALYZER requirements, so until there's no way to configure it... - }, - - _initDefaultColorSceneScale: function(){ - var colorAxis = this.panel.axes.color; - return colorAxis ? - colorAxis.sceneScale({nullToZero: false}) : - def.fun.constant(pvc.defaultColor) - ; - }, - - defaultColorSceneScale: function(){ - return this._defaultColorSceneScale || - (this._defaultColorSceneScale = this._initDefaultColorSceneScale()); - } -}); -- libgit2 0.21.2